Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac: Resolve all instances of a Type

Tags:

c#

autofac

Given the following registrations

builder.Register<A>().As<I>(); builder.Register<B>().As<I>(); builder.Register<C>().As<I>();  var container = builder.Build(); 

I am looking to resolve all instances of type I as a IEnumerable (Array or Collection it doesn't matter).

In Windsor I would have written the following.

foreach(I i in container.ResolveAll<I>()) {  ... } 

I am migrating from Windsor to Autofac 1.4.4.561 but can't see the equivalent syntax.

like image 538
crowleym Avatar asked Sep 10 '09 15:09

crowleym


2 Answers

For current versons of Autofac: ( 2.0+, so anything you should be using today)

You register multiple ILoggers (for example):

var builder = new ContainerBuilder();  builder.Register<ConsoleLogger>()   .As<ILogger>();  builder.Register<EmailLogger>()   .As<ILogger>()   .PreserveExistingDefaults(); //keeps console logger as the default 

Then get all ILoggers:

var loggers = container.Resolve<IEnumerable<ILogger>>(); 

You don't need to do anything special, just ask for an IEnumerable<T> of the desired type. Autofac has collection support out of the box, along with other adapters that can wrap your components with additional functionality.

This is the same usage as the pre-2.x ImplicitCollectionSupportModule, but baked right in.

For old versions (0.X - 1.4)

Two ways:

1) Use the collection registration

var builder = new ContainerBuilder(); builder.RegisterCollection<ILogger>()   .As<IEnumerable<ILogger>>();  builder.Register<ConsoleLogger>()   .As<ILogger>()   .MemberOf<IEnumerable<ILogger>>();  builder.Register<EmailLogger>()   .As<ILogger>()   .MemberOf<IEnumerable<ILogger>>(); 

Then:

var loggers = container.Resolve<IEnumerable<ILogger>>(); 

which gives you an IEnumerable.

or 2) You can use the ImplicitCollectionSupport module, which will make the code work like newer versions of Autofac:

builder.RegisterModule(new ImplicitCollectionSupportModule()); builder.Register(component1).As<ILogger>; builder.Register(component2).As<ILogger>; 

Then resolve a collection of ILogger rather than looking for resolving all.

var loggers = container.Resolve<IEnumerable<ILogger>>(); 

which gives you an IEnumerable, again.

like image 66
Philip Rieck Avatar answered Sep 21 '22 05:09

Philip Rieck


An update for the sake of the new (2.x) version. All you need now is:

container.Resolve<IEnumerable<I>>(); 

There's no longer a need for RegisterCollection() or ImplicitCollectionSupportModule - this functionality comes out of the box.

like image 24
Nicholas Blumhardt Avatar answered Sep 18 '22 05:09

Nicholas Blumhardt