Reputation: 719
Suppose I have 3 classes, Program
, A
(with dependencies D1
and D2
) and B
(with dependencies D3
and D4
). Program
initialises an IOC container and registers a bunch of types before creating an instance of A
.
class Program
{
static void Main(string[] args)
{
IOC ioc = new IOC();
//register types
A a = ioc.Resolve<A>();
}
}
At some point later on, a
needs to create an instance of B
, injecting its two dependencies into the constructor.
Question: How should a
resolve the dependencies of B
? I have been led to believe that passing the IOC container around i.e. injecting it into A
is the Service Locator pattern, which is bad. If B
created C
with its dependencies, B
would also need to have the container injected, and the container would be littered throughout my code. This sounds like a testing nightmare. Using a global static doesn't sound much better.
Upvotes: 2
Views: 299
Reputation: 6791
At some point later on,
A
needs to create an instance of 'B', injecting its two dependencies into the constructor.
In this case, A
must take a dependency on a BFactory
that can create the B
's for it.
Upvotes: 0
Reputation: 172646
It's actually simple. If A
needs B
, it should accept B
as constructor argument:
public class A
{
private readonly D1 d1;
private readonly D2 d2;
private readonly B b;
public A(D1 d1, D2 d2, B b) {
this.d1 = d1;
this.d2 = d2;
this.b = b;
}
}
public class B
{
private readonly D3 d3;
private readonly D4 d4;
private readonly C c;
public B(D3 d3, D4 d4, C c) {
this.d3 = d3;
this.d4 = d4;
this.c = c;
}
}
This way you build up object graphs recursively and you can get very deep object graphs, which is completely fine. This way you only need the container in the startup path of your application (a.k.a. the Composition Root).
Whether or not A
needs B
'later on', or just sometimes, or hardly ever is irrelevant. Building object graphs should be fast and whether or not B
is created needlessly should therefore not be an issue.
Upvotes: 1
Reputation: 11017
Ideally you should never inject container to your classes just to resolve the the dependencies. Rather you register instances in in separate place probably your startup class where in runtime application should be able to resolve dependencies automatically from the registered instances with container.
look at following example how an IOC container typically register its instances
Register
SimpleIoc.Default.Register< IDataService, DataService >(); SimpleIoc.Default.Register< MainViewModel >();
SimpleIoc.Default.Register< SecondViewModel >();
Resolve
SimpleIoc.Default.GetInstance< MainViewModel >();
Upvotes: 0