Allright. I finally understood all those complicated concepts of DI even IoC, containers, and so on and on. But there is something I'm missing still.
Say that I have a class called SomeClass
that will instaciate in his constructor one of the classes that implememnts IFirstLevelOfAbstraction
. The classes that implements IFirstLevelOfAbstraction
are SubClass1
and SubClass2
. Those classes I mentioned instanciate a class implementing ISecondLevelOfAbstraction
, which are SubClass3
and SubClass4
.
TL;DR here is the image.
Using unity in my entry point this should look something like this:
IUnityContainer container = new UnityContainer();
container.RegisterType<SomeClass>();
container.RegisterType<IFirstLevelOfAbstraction, SubClass1>();
container.RegisterType<IFirstLevelOfAbstraction, SubClass2>();
container.RegisterType<ISecondLevelOfAbstraction, SubClass3>();
container.RegisterType<ISecondLevelOfAbstraction, SubClass4>();
var someClass= container.Resolve<SomeClass>();
Question Being: How do I choose which path will the DI have in the container?
i.e The instance of IFirstLevelOfAbstraction
being SubClass1
and for ISecondLevelOfAbstraction
being SubClass4
.
How do I easily change this later on?
Having so many DI nested isn't an anti-pattern? Why? Why is this any good?
I feel like nobody uses this. It's not even native in C#.
One way to do it is not to register SubClass1
, SubClass2
,SubClass3
, or SubClass4
and then choose such dependencies when you resolve. Here is an example:
IUnityContainer container = new UnityContainer();
var someClass = container.Resolve<SomeClass>(
new DependencyOverride<IFirstLevelOfAbstraction>(new ResolvedParameter<SubClass1>()),
new DependencyOverride<ISecondLevelOfAbstraction>(new ResolvedParameter<SubClass4>()));
If this is not an option for you (you don't want to specify anything at resolve time), you need to use named registrations. I wouldn't recommend going that route though.
Since you have multiple implementations for a single interface, I recommend that you use Pure DI. See my article here for a reason why.
Here is how your code would look like with Pure DI:
var someClass =
new SomeClass(
new SubClass1(
new SubClass4()));