I`m confused about Dependency Injection implementation in one concrete example.
Let's say we have a SomeClass class that has a dependency of type IClassX.
public class SomeClass
{
public SomeClass(IClassX dependency){...}
}
Creation of concrete implementations of IClassX interface depends on runtime parameter N.
With given constructor, I can't configure DI container(Unity is used), because I don't know what implementation of IClassX will be used in runtime.
Mark Seemann in his book Dependency Injection In .Net suggests that we should use Abstract Factory as an injection parameter.
Now we have SomeAbstractFactory that returns implementations of IClassX based on runtime paramater runTimeParam.
public class SomeAbstractFactory
{
public SomeAbstractFactory(){ }
public IClassX GetStrategyFor(int runTimeParam)
{
switch(runTimeParam)
{
case 1: return new ClassX1();
case 2: return new ClassX2();
default : return new ClassDefault();
}
}
}
SomeClass now accepts ISomeAbstractFactory as an injection parameter:
public class SomeClass
{
public SomeClass(ISomeAbstractFactory someAbstractfactory){...}
}
And that's fine. We have only one composition root where we create the object graph. We configure Unity container to inject SomeAbstractFactory to SomeClass.
But, let's assume that classes ClassX1 and ClassX2 have their own dependencies:
public class ClassX1 : IClassX
{
public ClassX1(IClassA, IClassB) {...}
}
public class ClassX2 : IClassX
{
public ClassX2(IClassA, IClassC, IClassD) {...}
}
How to resolve IClassA, IClassB, IClassC and IClassD dependencies?
1. Injection through SomeAbstractFactory constructor
We can inject concrete implementations of IClassA, IClassB, IClassC and IClassD to SomeAbstractFactory like this:
public class SomeAbstractFactory
{
public SomeAbstractFactory(IClassA classA, IClassB classB, IClassC classC, IClassD classD)
{...}
...
}
Unity container would be used in the initial composition root and then use poor man’s DI to return concrete ClassX1 or ClassX2 based on parameter runTimeParam
public class SomeAbstractFactory
{
public SomeAbstractFactory(IClassA classA, IClassB classB, IClassC classC, IClassD classD){...}
public IClassX GetStrategyFor(int runTimeParam)
{
switch(runTimeParam)
{
case 1: return new ClassX1(classA, classB);
case 2: return new ClassX2(classA, classC, classD);
default : return new ClassDefault();
}
}
}
Problems with this approach:
SomeAbstractFactory knows about dependencies that don`t really belong to it.
Deeper object graph would require to change both SomeAbstractFactory constructor and class implementation
DI container would not be used to resolve dependencies, poor man`s DI must be used
2. Explicit call to DI container
Instead of “newing up” ClassX1 or ClassX2, we would resolve them by using a DI container.
public class SomeAbstractFactory
{
public SomeAbstractFactory(IUnityContainer container){...}
public IClassX GetStrategyFor(int runTimeParam)
{
switch(runTimeParam)
{
case 1: return container.Resolve<IClassX>("x1");
case 2: return container.Resolve<IClassX>("x2");
default : return container.Resolve<IClassX>("xdefault");
}
}
}
Problems with this approach:
DI container is passed into SomeAbstractFactory
DI Resolve method is not used only at the composition root (ServiceLocator anti-pattern)
Is there another more suitable approach?
The example below shows how to do this with Unity. This blog post explains it a little better using Windsor. The underlying concept is exactly the same for each, just slightly different implementation.
I would rather allow my abstract factory to access the container. I view the abstract factory as a way to prevent dependency on the container - my class only depends on IFactory, so it's only the implementation of the factory that uses the container. Castle Windsor goes a step further - you define the interface for the factory but Windsor provides the actual implementation. But it's a good sign that the same approach works in both cases and you don't have to change the factory interface.
In the approach below, what's necessary is that the class depending on the factory passes some argument that allows the factory to determine which instance to create. The factory is going to convert that to a string, and the container will match it with a named instance. This approach works with both Unity and Windsor.
Doing it this way the class depending on IFactory doesn't know that the factory is using a string value to find the correct type. In the Windsor example a class passes an Address object to the factory, and the factory uses that object to determine which address validator to use based on the address's country. No other class but the factory "knows" how the correct type is selected. That means that if you switch to a different container the only thing you have to change is the implementation of IFactory. Nothing that depends on IFactory has to change.
Here's sample code using Unity:
public interface IThingINeed
{}
public class ThingA : IThingINeed { }
public class ThingB : IThingINeed { }
public class ThingC : IThingINeed { }
public interface IThingINeedFactory
{
IThingINeed Create(ThingTypes thingType);
void Release(IThingINeed created);
}
public class ThingINeedFactory : IThingINeedFactory
{
private readonly IUnityContainer _container;
public ThingINeedFactory(IUnityContainer container)
{
_container = container;
}
public IThingINeed Create(ThingTypes thingType)
{
string dependencyName = "Thing" + thingType;
if(_container.IsRegistered<IThingINeed>(dependencyName))
{
return _container.Resolve<IThingINeed>(dependencyName);
}
return _container.Resolve<IThingINeed>();
}
public void Release(IThingINeed created)
{
_container.Teardown(created);
}
}
public class NeedsThing
{
private readonly IThingINeedFactory _factory;
public NeedsThing(IThingINeedFactory factory)
{
_factory = factory;
}
public string PerformSomeFunction(ThingTypes valueThatDeterminesTypeOfThing)
{
var thingINeed = _factory.Create(valueThatDeterminesTypeOfThing);
try
{
//This is just for demonstration purposes. The method
//returns the name of the type created by the factory
//so you can tell that the factory worked.
return thingINeed.GetType().Name;
}
finally
{
_factory.Release(thingINeed);
}
}
}
public enum ThingTypes
{
A, B, C, D
}
public class ContainerConfiguration
{
public void Configure(IUnityContainer container)
{
container.RegisterType<IThingINeedFactory,ThingINeedFactory>(new InjectionConstructor(container));
container.RegisterType<IThingINeed, ThingA>("ThingA");
container.RegisterType<IThingINeed, ThingB>("ThingB");
container.RegisterType<IThingINeed, ThingC>("ThingC");
container.RegisterType<IThingINeed, ThingC>();
}
}
Here's some unit tests. They show that the factory returns the correct type of IThingINeed after inspecting what was passed to its Create() function.
In this case (which may or may not be applicable) I also specified one type as a default. If nothing is registered with the container that exactly matches the requirement then it could return that default. That default could also be a null instance with no behavior. But all of that selection is in the factory and container configuration.
[TestClass]
public class UnitTest1
{
private IUnityContainer _container;
[TestInitialize]
public void InitializeTest()
{
_container = new UnityContainer();
var configurer = new ContainerConfiguration();
configurer.Configure(_container);
}
[TestCleanup]
public void CleanupTest()
{
_container.Dispose();
}
[TestMethod]
public void ThingINeedFactory_CreatesExpectedType()
{
var factory = _container.Resolve<IThingINeedFactory>();
var needsThing = new NeedsThing(factory);
var output = needsThing.PerformSomeFunction(ThingTypes.B);
Assert.AreEqual(output, typeof(ThingB).Name);
}
[TestMethod]
public void ThingINeedFactory_CreatesDefaultyTpe()
{
var factory = _container.Resolve<IThingINeedFactory>();
var needsThing = new NeedsThing(factory);
var output = needsThing.PerformSomeFunction(ThingTypes.D);
Assert.AreEqual(output, typeof(ThingC).Name);
}
}
This same factory can be implemented using Windsor, and the factory in the Windsor example could be done in Unity.
Related
I'm trying to register by convention multiple implementation of single interface and later use all those interfaces as dependency in other classes. Unfortunatelly, I'm having some problems trying to do so.
I want to register multiple implementation, so I added WithName.TypeName druing registration but this seems to be causing problems. Without it, I can't register multiple implementations for single interface.
Below is simple example which is not working. Unity is throwing exception and I don't know why.
Unity.ResolutionFailedException: 'Resolution failed with error: No
public constructor is available for type KYPClient.IConf.
namespace KYPClient
{
public interface IConf
{
string conf();
}
public class Conf : IConf
{
public string conf()
{
return "conf";
}
}
public interface ILoader
{
string load();
}
public class Load_1 : ILoader
{
public string load()
{
return "load-1";
}
}
public class Load_2 : ILoader
{
public string load()
{
return "load-2";
}
}
public class MainCls
{
private IConf _conf;
private IEnumerable<ILoader> _loaders;
public MainCls(IConf conf, IEnumerable<ILoader> loaders)
{
_conf = conf;
_loaders = loaders;
}
public void Run()
{
System.Console.WriteLine(_conf.conf());
foreach (var l in _loaders)
{
Console.WriteLine(l.load());
}
}
}
internal static class Client
{
private static void Main()
{
using var container = new UnityContainer();
container.RegisterTypes(
AllClasses.FromAssemblies(typeof(MainCls).Assembly),
WithMappings.FromAllInterfaces,
WithName.TypeName,
WithLifetime.ContainerControlled);
var main = container.Resolve<MainCls>();
main.Run();
}
}
}
The issue is you're using the WithName.TypeName option. This means that each type from the assembly is done as a named registration in the container. This is a good thing in your case because you are registering multiple ILoader instances, so the container has to be able to differentiate them. However, it also means that when it's being resolved, you have to pass the name in order for the container to find it.
In other words, when the container sees the constructor public MainCls(IConf conf, IEnumerable<ILoader> loaders) it interprets that as "inject the IConf instance with the default name" which doesn't exist in your container. Your IConf is registered with the name "Conf" (or possibly "KYPClient.Conf", I'm not sure, as I've never used the RegisterTypes method).
Thus, you have to explicitly name it in your constructor. Also, per How to configure Unity to inject an array for IEnumerable you need an array to get all the registered ILoader types.
public MainCls([Dependency("Conf")] IConf conf, ILoader[] loaders)
Of course, there are some drawbacks to using named dependencies (such as, what happens if you refactor and rename your class). Take a look at the second answer to With Unity how do I inject a named dependency into a constructor? for a strategy around that using a factory pattern.
TL;DR. I have a circular dependency and no idea how to break it.
Main.csproj: has Program.cs which manually instantiates DiService
var diService = new DiService(new Container());
diService.Register();
The register method searches CurrentDomain for assemblies and registers collections where multiple implementations exist for a given interface or else registers concretions on a 1-1 basis.
It then uses the Container to instantiate an abstract factory.
var diFactory = diService.Registry.GetInstance<IDiFactory>();
Here's the factory
public class DiFactory : IDiFactory
{
private readonly Container registry;
public DiFactory(Container registry)
{
this.registry = registry;
}
public T Get<T>()
{
var reqT = typeof(T);
return (T) registry.GetInstance(reqT);
}
}
The project dependencies in the solution look like this:
Main -> A -> B,E
B -> C,D,E
C -> D,E
D -> E
DiService and DiFactory live in project B with the other services. Not that it matters. I think I'd have the same problem if they were in Main.
All objects in projects B to E have a constructor injected DiFactory so they can decide what objects they need at run time. But for C to make use of it, it must depend on B, which is a circular dependency.
If I move the DI stuff to a new project F, then all projects can depend on that but how does the factory reference the types in the other projects without creating another circular dependency?
I followed the documentation for IRequestHandler, I just didn't do the dictionary. Most likely I have a design flaw but I can't see what it is.
Here's an example of the interactions between objects for LinqPad - doesn't compile but it looks right.
void Main()
{
var diService = new Mine.Services.MyDiService();
var diFactory = diService.Container.GetInstance<Mine.Services.IMyFactory>();
var rand = new Random();
var next = rand.Next(1, 100);
var task = next % 2 == 0
? diFactory.Get<Mine.Tasks.EvenTask>()
: (Mine.Tasks.IMyTask)diFactory.Get<Mine.Tasks.OddTask>();
task.Perform();
}
namespace Mine.Common
{
public class MyCommonObject { }
}
namespace Mine.Services
{
public class FakeContainer
{
public T GetInstance<T>() { return default(T); }
}
public interface IMyOtherService { void DoSomethingElse(); }
public class MyOtherService : IMyOtherService
{
public void DoSomethingElse()
{
throw new NotImplementedException();
}
}
public class MyService
{
private readonly IMyFactory myFactory;
public MyService(IMyFactory myFactory)
{
this.myFactory = myFactory;
}
public void MyServiceMethod()
{
var thing = myFactory.Get<Mine.Common.MyCommonObject>();
}
}
public interface IMyFactory { T Get<T>(); }
public class MyDiService
{
public FakeContainer Container;
}
public class MyFactory : IMyFactory
{
private FakeContainer Container;
public MyFactory(FakeContainer container)
{
// obviously this is really a SImple Injector Container
Container = container;
}
public T Get<T>()
{
return default(T);
}
}
}
namespace Mine.Kernel {
public interface IMyMultiConcrete { void Do(); }
public class MyConcreteBase : IMyMultiConcrete
{
protected readonly Mine.Services.IMyFactory MyFactory;
public MyConcreteBase(Mine.Services.IMyFactory myFactory)
{
MyFactory = myFactory;
}
public void Do()
{
MyFactory.Get<Mine.Common.MyCommonObject>();
}
}
public class MyConcrete1 : MyConcreteBase
{
public MyConcrete1(Mine.Services.IMyFactory myFactory) : base(myFactory) {}
public void Do()
{
MyFactory.Get<Mine.Common.MyCommonObject>();
}
}
}
namespace Mine.Tasks
{
public interface IMyTask { void Perform(); }
public class TaskBase : IMyTask
{
protected readonly Mine.Services.IMyOtherService MyOtherService;
public TaskBase(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
{
MyOtherService = myOtherService;
}
public void Perform()
{
MyOtherService.DoSomethingElse();
}
}
public class OddTask : TaskBase
{
public OddTask(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
: base(myFactory, myOtherService) { }
}
public class EvenTask : TaskBase
{
public EvenTask(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
: base(myFactory, myOtherService) { }
}
}
This IDiFactory abstraction you are describing is not an implementation of the Abstract Factory design pattern—it is an implementation of the Service Locator pattern. Service Locator, however, is an anti-pattern and you should stop using it because its numerous downsides.
Instead, classes should not be able to request an unbound set of dependencies from a Service Locator, but neither should they typically be able to request a fixed set of dependencies using an Abstract Factory. Instead, classes should statically declare their required dependencies through the constructor.
This change might already fix the circular dependency as you will remove the IDiFactory (that is causing the cycle) in the first place.
DiService and DiFactory live in project B with the other services. Not that it matters.
It does matter where you wire up your dependencies. Dependencies should be wired up in your Composition Root and this Composition Root should live
As close as possible to the application’s entry point.
This most likely means that you should move this to your Console application. When you move that code, only the start-up assembly will take a dependency on the used DI Container. At that point, it becomes irrelevant to hide the DI Container behind an Abstraction (as your DiService seems to imply). Hiding is not needed anymore, because no other parts of the application except the Composition Root will have any knowledge about how dependency graphs are built. Hiding the DI Container behind an abstraction, at that point, doesn't increase maintainability any longer.
There might be an easier way, but what I typically end up doing is to have a separate assembly containing interfaces for everything I need to inject.
The main assembly (or B could do it in your case) performs the binding of interfaces to concrete implementations and everyone can reference the interfaces assembly without creating any circular dependencies.
The interface for the factory should also be in that assembly.
For brevity, I'll use some short and generalized naming conventions. If I have:
public class Factory : IFactory
{
private readonly string dbConnection;
public Factory(string dbConnection)
{
this.dbConnection= dbConnection;
}
public IDataContext Create() => new DataContext(dbConnection);
}
The Factory class has a field, which is being set by the Constructor. How does Simple Injector support the passing of that parameter? If you implement:
public class Service
{
private IFactory Factory { get; }
public Service(IFactory factory)
{
Factory = factory;
}
public void Save()
{
using(var context = Factory.Create())
context.Insert(...);
}
}
The parameter is never actually passed to or through the Factory when it is initialized or instantiated. When you register the dependencies, it doesn't look it is possible:
ContainerFactory.Register<IFactory, Factory>(Lifestyle.Transient);
I was looking into the IEventHandler interface, that is apart of Simple Injector which looks like it would address this issue, but is that how you're supposed to pass a parameter in this instance?
container.RegisterSingleton<IFactory>(new Factory("constr"));
With Autofac IoC container, say one has the following scenario:
public interface IHaveASpecialProperty
{
SpecialType SpecialProperty { get; }
}
public class HaveASpecialPropertyImpl : IHaveASpecialProperty
{
// implementation
}
public class SomeComponent
{
public SomeComponent(SpecialType special)
{
_special = special;
// rest of construction
}
private readonly SpecialType _special;
// implementation: do something with _special
}
// in composition root:
containerBuilder.RegisterType<HaveASpecialPropertyImpl>
.As<IHaveASpecialProperty>();
containerBuilder.RegisterType<>(SomeComponent);
Is there a way to register, within Autofac container, the HaveASpecialPropertyImpl type to act as a kind of provider/ factory of SpecialType instances?
What I currently have is this classic approach:
public class SomeComponent
{
public SomeComponent(IHaveASpecialProperty specialProvider)
{
_special = specialProvider.SpecialProperty;
// rest of construction
}
private readonly SpecialType _special;
// implementation: do something with _special
}
The rationale is basically related to the Law of Demeter: specialProvider is used only to grab a SpecialType instance, which instead is the actual dependency needed and used by SomeComponent, so it seems reasonable to just inject that SpecialType instance, without concerning SomeComponent on where that instance comes from.
PS: I've read about Delegate Factories, not sure if that's the (only?) way to go.
You can register a delegate :
builder.Register(c => c.Resolve<IHaveASpecialProperty>().SpecialProperty)
.As<ISpecialType>();
Using this registration, each time you will resolve a ISpecialType Autofac will resolve a IHaveASpecialProperty and return the SpecialProperty property value as ISpecialType.
I am using Unity for dependency injection and I want to control at runtime, which particular type is resolved and passed into a constructor as a dependency.
I have an interface:
public interface IDatabase
{
void DoSomething();
}
That is implemented by two classes:
public class SQLDatabase : IDatabase
{
public void DoSomething()
{
//Do Something on a SQL server database...
}
}
public class OracleDatabase : IDatabase
{
public void DoSomething()
{
//Do Something on an Oracle database...
}
}
A third class has a dependency on IDatabase
public class DataService: IDataService
{
public DataService(IDatabase database)
{
database.DoSomething();
}
}
The module registers each class with Unity and the two IDatabase types are given specific names so that they can be differentiated:
container.RegisterType<IDatabase, SQLDatabase>("SQLDatabase");
container.RegisterType<IDatabase, OracleDatabase>("OracleDatabase");
container.RegisterType<IDataService, DataService>();
I need to create an instance of a Consumer, at which point I want to specify which of the two types that implement IDatabase are to be used/injected by Unity, but I don't know how to tell Unity which specific type to construct/resolve? I guess I want something like this (Pseudo code):
public class Consumer
{
IDataService dataService = null;
public Consumer(string runtimeChoice)
{
if (runtimeChoice == "SQLSERVER")
{
dataService = _container.Resolve<IDataService>("SQLDatabase");
}
else if (runtimeChoice == "Oracle")
{
dataService = _container.Resolve<IDataService>("OracleDatabase");
}
}
}
So, how do I tell Unity to resolve the IDatabase type, using the specific named type, and pass it into the constructor of dependent objects, but doing it at runtime?
There are two things I would change, I would try to ensure those magic strings were handled as close to their source as possible and I would try to ensure my code was container agnostic.
I would have the following interface:
public interface IDataServiceFactory
{
IDataService CreateSqlDataService();
IDataService CreateOracleDataService();
}
With an implementation like so:
public class DataServiceFactory : IDataServiceFactory
{
private readonly Func<IDataService> _sqlDataServiceFactory;
private readonly Func<IDataService> _oracleDataServiceFactory;
public DataServiceFactory(Func<IDataService> sqlDataServiceFactory, Func<IDataService> oracleDataServiceFactory)
{
_sqlDataServiceFactory = sqlDataServiceFactory;
_oracleDataServiceFactory = oracleDataServiceFactory;
}
public IDataService CreateSqlDataService()
{
return _sqlDataServiceFactory();
}
public IDataService CreateOracleDataService()
{
return _oracleDataServiceFactory();
}
}
I would then register this with your IUnityContainer like so:
_container.RegisterType<IDataService, DataService>("SQLDataService",
new InjectionConstructor(new ResolvedParameter<IDatabase>("SQLDatabase")));
_container.RegisterType<IDataService, DataService>("OracleDataService",
new InjectionConstructor(new ResolvedParameter<IDatabase>("OracleDatabase")));
_container.RegisterType<IDataServiceFactory, DataServiceFactory>(new InjectionConstructor(
new ResolvedParameter<Func<IDataService>>("SQLDataService"),
new ResolvedParameter<Func<IDataService>>("OracleDataService"));
Now whatever was previously creating your Consumer instances should now have a dependency on IDataServiceFactory and should handle the runtime value to call the correct method CreateSqlDataService() or CreateOracleDataService().
All of your runtime code is now container agnostic and the magic strings are handled right next to their source.
I was able to resolve the correct type using a DependencyOverride, which itself obtained the required type from the unity container. So the consumer becomes:
public class Consumer
{
IDataService dataService = null;
public Consumer(string runtimeChoice)
{
DependencyOverride<IDatabase> dependency = null;
if (runtimeChoice == "SQLSERVER")
{
dependency = new DependencyOverride<IDatabase>
(Container.Resolve<IDatabase>("SQLDatabase"));
}
else if (runtimeChoice == "Oracle")
{
dependency = new DependencyOverride<IDatabase>
(Container.Resolve<IDatabase>("OracleDatabase"));
}
dataService = _container.Resolve<IDataService>(dependency);
}
}
I have a similar requirement where I need to resolve a 'widgetbuilder' type at runtime. In my Unity Configuration I register my two types of widget builders:-
container.RegisterType<IWidgetBuilder, SinglePointWidgetBuilder>("SinglePointWidgetBuilder");
container.RegisterType<IWidgetBuilder, CurrentVsTargetWidgetBuilder>("CurrentVsTargetWidgetBuilder");
I then resolve them at runtime by:-
var container = UnityConfig.GetConfiguredContainer();
var widgetBuilder = container.Resolve<IWidgetBuilder>("SinglePointWidgetBuilder");