Does the Funq IoC container support resolving all registrations for a type? Something like either of these:
IEnumerable<IFoo> foos = container.Resolve<IEnumerable<IFoo>>();
IEnumerable<IFoo> foos = container.ResolveAll<IFoo>();
Funq does not have a ResolveAll
method, but you can simply register an IEnumerable<IFoo>
and resolve it with Resolve<IEnumerable<IFoo>>()
as you show in your question.
In general however, it is better not to request the container for collections, but use composites instead. This way you can simply inject an IFoo
as a dependency, instead of forcing consumers of that dependency to iterate the list. Instead you embed the code that loops the list of IFoo
instances inside the composite. This keeps your code DRY and doesn't force you to go through the (possible) dozens of foreach (var foo in foos)
statements scattered throughout the application, when a change has to be made in the way the items are iterated. Or let me put it in an other way: it is not the responsibility of a consumer to know how to iterate all IFoo
s.
Here is an example of an IFoo
Composite:
// A composite is something that implements an interface
// (in this case IFoo) and wraps a list of items of that
// same interface.
public class FooComposite : IFoo
{
private readonly IEnumerable<IFoo> foos;
public FooComposite(params IFoo[] foos)
{
this.foos = foos;
}
void IFoo.FooThatThing(IBar bar)
{
foreach (var foo in this.foos)
{
foo.FooThatThing(bar);
}
}
}
Instead of registering an IEnumerable<IFoo>
, you can register a CompositeFoo
as IFoo
:
container.Register<IFoo>(c => new CompositeFoo(
new Foo1(), new Foo2(), new Foo3()));
Now you can let the container inject that CompositeFoo
in consumers that take an IFoo
argument, which makes them unaware that they are in fact dealing with a list of IFoo
elements.
UPDATE:
Using this composite pattern, you can easily control the lifetime of each IFoo
item. It's just a matter of calling back into the container. With Funq,it would look like this:
container.Register<IFoo>(c => new CompositeFoo(
c.Resolve<Foo1>(),
c.Resolve<Foo2>(),
c.Resolve<Foo3>()));
This way you can register Foo1
as singleton and Foo2
as transient for instance. When the CompositeFoo
is reused however, Foo2
will not really be transient, but it's just a matter of changing the CompositeFoo
and its registration to solve this problem. For instance, you can change your CompositeFoo
to the following:
public class FooComposite : IFoo
{
private readonly Func<IFoo>[] fooFactories;
public FooComposite(params Func<IFoo>[] fooFactories)
{
this.fooFactories = fooFactories;
}
void IFoo.FooThatThing(IBar bar)
{
foreach (var fooFactory in this.fooFactories)
{
var foo = fooFactory();
foo.FooThatThing(bar);
}
}
}
Now instead of injecting some IFoo
s into the constructor, we can inject some lambdas in it:
container.Register<IFoo>(c => new CompositeFoo(
() => c.Resolve<Foo1>(),
() => c.Resolve<Foo2>(),
() => c.Resolve<Foo3>()));
This will ensure that every time CompositeFoo
's FooThatThing
is called, the container is queried for new IFoo
instances. This allows FooThatThing
to be called multiple times by the same consumer, and even allows CompositeFoo
to be registered as singleton.
This advice holds for all containers and Dependency Injection in general, and is not specific to the use of Funq.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With