AutoFac Register confusion - dependency-injection

Hi I am just been looking at AutoFac and following their getting-started tutorial
http://autofac.readthedocs.org/en/latest/getting-started/index.html
having followed it and understanding how their services work I wanted to try to create a new implementation on the same interface type
builder.RegisterType<TodayWriter>().As<IDateWriter>();
builder.RegisterType<TomorrowWriter>().As<IDateWriter>();
Both implentations contain the same code
public class TomorrowWriter : IDateWriter
{
private IOutput _output;
public TomorrowWriter(IOutput output)
{
this._output = output;
}
public void WriteDate()
{
this._output.Write(DateTime.Today.AddDays(1).ToShortDateString());
}
}
So TodaysWriter is the same apart from the WriteDate method displaying
this._output.Write(DateTime.Today.ToShortDateString());
instead.
So now using the application, how do I determine what implementation to use as both methods are called WriteDate()
using(var scope = Container.BeginLifetimeScope())
{
var writer = scope.Resolve<IDateWriter>();
// Is this using todaysWriter or TomorrowWriter?
writer.WriteDate();
}
Am I using this wrong?
Thanks

To differentiate between different implementations of the same interface look at named and keyed services in the docs.
Alternatively you can roll your own by registering a DateWriterFactory and having a method on that to get a specific IDateWriter implementation. something like:
public class DateWriterFactory
{
IDateWriter GetWriter(string writerName)
{
if (writername=="TodayWriter")
return new TodayWriter();
if (writername=="TomorrowWriter")
return new TomorrowWriter();
}
}
obviously the implementation of the factory could be as complex or as simple as you need. Or you could just have methods to get the fixed writers rather than pass in a string.

Related

How to get the instance of an injected dependency, by its type using Umbraco.Core.Composing (Umbraco 8)

I need to find a way to get an instance of DataProcessingEngine without calling it's constractor.
I am trying to find a way to do so using the registered DataProcessingEngine in composition object (please see the following code). But I could not find a way to do so.
Anyone have a suggestion? Thanks in advance.
public class Composer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IDataProcessingEngine, DataProcessingEngine>(Lifetime.Singleton);
//DataProcessingEngine dataProcessing = compostion.Resolve<IDataProcessingEngine>()??//no resolve function exists in Umbraco.Core.Composing
SaveImagesThread(dataProcessingEngine);
}
public Task SaveImagesThread(IDataProcessingEngine dataProcessingEngine)//TODO - decide async
{
string dataTimerTime = WebConfig.SaveProductsDataTimer;
double time = GetTimeForTimer(dataTimerTime);
if (time > 0)
{
var aTimer = new System.Timers.Timer(time);
aTimer.Elapsed += new ElapsedEventHandler(dataProcessingEngine.SaveImages);
aTimer.Start();
}
return default;
}
}
For all of you who are looking for a way to call a function (that's defined in another class in your code, an Engine or ...) from the composer(where the app starts) and want to avoid calling this function's class' constractor. I've found another way to do so:
public class QueuePollingHandler
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class SubscribeToQueuePollingHandlerComponentComposer :
ComponentComposer<SubscribeToQueuePollingHandler>
{ }
public class SubscribeToQueuePollingHandler : IComponent
{
private readonly IDataProcessingEngine _dataProcessingEngine;
public SubscribeToQueuePollingHandler(IDataProcessingEngine
dataProcessingEngine)
{
_dataProcessingEngine = dataProcessingEngine;
SaveImagesThread(_dataProcessingEngine);
}
public void SaveImagesThread(IDataProcessingEngine
dataProcessingEngine)
{
....
}
}
And the logic explenation: You create a class (SubscribeToQueuePollingHandlerComponentComposer from the example) and define its base class to be ComponentComposer<Class_that_inherits_IComponent>.
And when you start the application you could see that it gets to the registered class' constractor (SubscribeToQueuePollingHandler constructor).
That's the way that I found to be able to call a function right when the application starts without needing to call its class constractor and actualy use dependency injection.

servicestack with funq - autowiring by convention

I have a service which takes an IMyDependency in its constructor. IMyDependency, MyDependency and the service all live in the same assembly. MyDependency has a single, public, parameterless constructor.
To my surprise, this did not work:
container.RegisterAutoWired<IMyDependency>();
It throws a "System.NullReferenceException".
It works if I do this:
container.RegisterAutoWiredAs<MyDependency, IMyDependency>();
But then, so does this:
container.RegisterAs<MyDependency, IMyDependency>();
So what is the difference? If 'auto wiring' cannot find a concrete implementation, and it makes no difference to whether services requiring the dependency can be resolved, then what is auto wiring?
Is Funq supposed to be able to find your concrete implementations by convention? If so, what is that convention, if not same-named-ness?
Thanks.
Do you mean "how can I implement a solution to search through assemblies and automatically register classes in ServiceStack IOC based on a convention?"
If so, I might have a solution for you:
Create an interface that your inject-able classes will implement.
Have your inject-able classes implement that interface.
In the boot-strapping code use reflection to search your assemblies and get a list of all of the classes that implement the inject-able interface.
Use reflection to get the class name and interface based on your conventions.
Call the ServiceStack IOC method RegisterAutoWiredType and pass in the class and interface to register them.
For example if our naming convention is ClassName IClassName:
private static void RegisterCustomTypes(Container container)
{
//Get the Assembly Where the injectable classes are located.
var assembly = Assembly.GetAssembly(typeof(IInjectable));
//Get the injectable classes
var types =assembly.GetTypes()
.Where(m => m.IsClass && m.GetInterface("IInjectable") != null);
//loop through the injectable classes
foreach (var theType in types)
{
//set up the naming convention
var className = theType.Name;
var interfaceName = string.Concat("I", className);
//create the interface based on the naming convention
var theInterface = theType.GetInterface(interfaceName);
//register the type with the convention
container.RegisterAutoWiredType(theType, theInterface);
}
}
public interface IInjectable
{
}
//This class can be injected
public interface ITestManager : IInjectable
{
void Execute(int id);
}
public class TestManager : ITestManager
{
public void Execute(int id)
{
throw new System.NotImplementedException();
}
}
For simple queries like this it's best to just contact the source, e.g. here is the source code for RegisterAutoWired:
public IRegistration<T> RegisterAutoWired<T>()
{
var serviceFactory = GenerateAutoWireFn<T>();
return this.Register(serviceFactory);
}
It generates an auto-wired factory over a Concrete implementation. An interface has no implementation, it needs to be a concrete class.
And the source code for RegisterAs:
public IRegistration<TAs> RegisterAs<T, TAs>() where T : TAs
{
return this.RegisterAutoWiredAs<T, TAs>();
}
Which is just a shorter alias you can use instead of RegisterAutoWiredAs.

Injecting multiple constructor parameters of the same type with Ninject 2.0

I'm using Ninject 2.0 to handle DI in one of my apps and I've come across something that's confusing me. Having zero documentation doesn't help too much either to be honest.
Say I have a constructor with the signature -
ctor(IServiceFactory factory1, IServiceFactory factory2)
{
this.factory1 = factory1;
this.factory2 = factory2;
}
Although these two services implement the same interface, they are quite different implementations and are used at different times so I don't want to inject an IEnumerable<IServiceFactory>.
My question is, when I'm binding the instances, how do I tell Ninject what to inject for each?
Thanks in advance.
Update
For the sake of anyone wanting to see the code would end up after reading Remo's links,...Here it is in brief. (I never realised C# had parameter attributes!)
//abstract factory
public interface IServiceFactory
{
Service Create();
}
//concrete factories
public class Service1Factory : IServiceFactory
{
public IService Create()
{
return new Service1();
}
}
public class Service2Factory : IServiceFactory
{
public IService Create()
{
return new Service2();
}
}
//Binding Module (in composition root)
public class ServiceFactoryModule : NinjectModule
{
public override void Load()
{
Bind<IServiceFactory>()
.To<Service1Factory>()
.Named("Service1");
Bind<IServiceFactory>()
.To<Service2Factory>()
.Named("Service2");
}
}
//consumer of bindings
public class Consumer(
[Named("Service1")] service1Factory,
[Named("Service2")] service2Factory)
{
}
First of all you have to ask yourself if using the same interface is correct if the implementations need to do a completely different thing. Normally, the interface is the contract between the consumer and the implementation. So if the consumer expects different things then you might consider to define different interfaces.
If you decide to stay with the same interface than you have to use conditional bindings. See the documentation about how this is done:
https://github.com/ninject/ninject/wiki/Contextual-Binding
https://github.com/ninject/ninject/wiki/Conventions-Based-Binding

How to create ObjectQuery for testing EF4 'Include' method

We are using EF4 and creating test cases for DAL layer (DAL layer is having linq query). We are using TypeMock as mocking framework. For testing, we are creating Fakecontext of ObjectContext and mocking CreateObjectSet method as follows:
Isolate.WhenCalled(() => fakeContext.Context.CreateObjectSet<User>)).WillReturnCollectionValuesOf(fakeUsers.AsQueryable());
The above is working fine. The issue is when we are trying to include related tables using 'Include'. We have extended the include method as follows:
public static IQueryable<T> Include<T>(this IQueryable<T> source, Expression<Func<T>> property)
{
var objectQuery = source as ObjectQuery<T>;
if (objectQuery != null)
{
var propertyPath = GetPropertyPath(property);
return objectQuery.Include(propertyPath);
}
return source;
}
So what happen is, in the above Include method the source type should be ObjectQuery<T>. But as we have mocked CreateObjectSet, source type in Include method is of Collection.Generic.List type. Kindly let us know how should we mock in the above case. Your timely help will be highly appreciable. Thanks
Object Services can be difficult to use when writing unit test. Unfortunately, there is not a good interface to mock for ObjectQuery<T> as you have found out. To handle this scenario I have created a wrapper class following the Repository pattern to encapsulate my ObjectContext and created a wrapper class to encapsulate ObjectQuery<T>:
public interface IMyObjectQuery<T> : IOrderedQueryable<T>
{
IMyObjectQuery<T> Include(string path);
}
public class MyObjectQuery<T> : IMyObjectQuery<T>
{
private ObjectQuery<T> _query;
public MyObjectQuery(ObjectQuery<T> query)
{
_query = query;
}
IMyObjectQuery<T> Include(string path)
{
//There is probably a better way to do this
//but you get the idea
return new MyObjectQuery(_query.Include(path));
}
//Implement IQueryable, IEnumerable...
}
And then it is a matter of implementing a Repository wrapper for your ObjectContext. Here is a link to get you started.
Add something like this:
public class MyRepository : IMyRespository
{
...
public IMyObjectQuery<T> CreateQuery<T>()
{
return new MyObjectQuery(_context.CreateQuery<T>());
}
...
}
This is probably not the simple solution that you were looking for, as it is not a trivial task. I think you will find that if you don't you will continue to encounter difficulty writing tests.

Best practices: Calling GetInstance method to instantiate object

Lets discuss one thing:
I have some simple interface:
public interface ICar
{
void StartEngine();
void StopEngine();
}
public interface IRadio
{
//doesn't matter
}
and some implementation:
public class SportCar : ICar
{
private IRadio radio;
public SportCar(IRadio radioObj)
{
radio = radioObj;
}
//all the rest goes here
}
also we have our StructureMap initialization code, and we calling it on Program initialization:
private void InitializeStructureMap()
{
ObjectFactory.Initialize(x=>
{
x.For<ICar>.Use<SportCar>();
x.For<IRadio>.Use<CarAudioSystem>();
});
}
And my question is: what is the best practice to instantiate SportCar? Is calling:
ObjectFactory.GetInstance<ICar>()
a good practice (now I don't now other way to resolve this)?
ObjectFactory.GetInstance is your starting point, that is what you use to resolve the first object in the hierarcy.
This is how i start my WinForms applications, the same technique should apply to WebForms, Windows Services and Console Applications:
var main = ObjectFactory.GetInstance<Main>();
Application.Run(main);
For ASP.NET MVC the framework allows you to register a factory that creates your controllers, but even in that factory you would call ObjectFactory.GetInstance to instanciate your controller.
As a side note:
When you do initialization, you don't explicitly need to map ICar to SportCar unless you have multiple ICar implementations, you can just do
x.Scan(a => { a.TheCallingAssembly(); a.WithDefaultConventions(); });
which wil map your interfaces with default implementations.

Resources