78

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.

Keith Pinson
  • 7,835
  • 7
  • 61
  • 104
crowleym
  • 2,532
  • 3
  • 22
  • 28
  • Any reason, that you want to share, for why you are moving from Windsor to Autofac? – Peter Lillevold Sep 10 '09 at 18:25
  • The thing that I really like with Autofac is being able to express dynamic component construction through lamda expressions. By using expressions as opposed to autowiring there is less room for misunderstanding of what the container is "doing" when it resolves a type (note: autofac supports autowiring if you prefer). Finally the Windsor API has become so huge as to cater for every possibility it gives the impression of complexity, when IOC as a concept is actually quite simple. Not saying I will never use Windsor again, just trying out the other options. – crowleym Sep 10 '09 at 20:51
  • 3
    I've considered moving from Windsor to Autofac. Windsor's API is confusing. –  Jan 27 '14 at 16:28

2 Answers2

101

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.

Philip Rieck
  • 32,368
  • 11
  • 87
  • 99
  • Perfect. Went for option one as its seems more efficient because the container "knows" what to put in the collection. Second option iterates though every registration in the container hierarchy looking for matching types. – crowleym Sep 10 '09 at 16:23
  • @philip-rieck hi, what does it means container.resolve in autofac?. If you dont use autofac, in which way you can declare Ilogger interface? thank you... – s_h Jun 01 '11 at 02:15
  • 1
    @sebastian_h if you are not using autofac, this answer will have no meaning for you. You may want to look here instead: http://stackoverflow.com/questions/5646820/logger-wrapper-best-practice – Philip Rieck Jun 01 '11 at 18:34
  • @philip-rieck thank you, I received an app using it and truly I have lots of doubts. best regards – s_h Jun 02 '11 at 02:53
  • Wow! This doesn't seem very intuitive. I was looking for a `ResolveAll` method similar to what Windsor Castle used to have in the old days (+1) – Leo May 06 '20 at 01:47
61

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.

Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101