web-dev-qa-db-fra.com

Autofac: résoudre toutes les instances d'un type

Étant donné les enregistrements suivants

builder.Register<A>().As<I>();
builder.Register<B>().As<I>();
builder.Register<C>().As<I>();

var container = builder.Build();

Je cherche à résoudre toutes les instances de type I en tant que IEnumerable (tableau ou collection, cela n'a pas d'importance).

À Windsor, j'aurais écrit ce qui suit.

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

Je migre de Windsor vers Autofac 1.4.4.561 mais je ne vois pas la syntaxe équivalente.

61
crowleym

Pour les versions actuelles d'Autofac: (2.0+, donc tout ce que vous devriez utiliser aujourd'hui)

Vous enregistrez plusieurs ILoggers (par exemple):

var builder = new ContainerBuilder();

builder.Register<ConsoleLogger>()
  .As<ILogger>();

builder.Register<EmailLogger>()
  .As<ILogger>()
  .PreserveExistingDefaults(); //keeps console logger as the default

Obtenez ensuite tous les ILoggers:

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

Vous n'avez rien à faire de spécial, demandez simplement un IEnumerable<T> du type souhaité. Autofac a un support de collecte prêt à l'emploi, ainsi que d'autres adaptateurs qui peuvent envelopper vos composants avec des fonctionnalités supplémentaires.

C'est le même usage que le ImplicitCollectionSupportModule pré-2.x, mais cuit directement.

Pour les anciennes versions (0.X - 1.4)

Deux manières:

1) Utilisez l'enregistrement de la collection

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>>();

Ensuite:

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

ce qui vous donne un IEnumerable.

ou 2) Vous pouvez utiliser le module ImplicitCollectionSupport, qui fera fonctionner le code comme les nouvelles versions d'Autofac:

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

Résolvez ensuite une collection d'ILogger plutôt que de chercher à tout résoudre.

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

ce qui vous donne à nouveau un IEnumerable.

81
Philip Rieck

Une mise à jour pour le bien de la nouvelle version (2.x). Il vous suffit maintenant:

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

Il n'y a plus besoin de RegisterCollection() ou ImplicitCollectionSupportModule - cette fonctionnalité sort de la boîte.

56
Nicholas Blumhardt