Autofac: Resolva todas as instâncias de um tipo
Pergunta
Tendo em conta os seguintes registos
builder.Register<A>().As<I>();
builder.Register<B>().As<I>();
builder.Register<C>().As<I>();
var container = builder.Build();
Eu estou olhando para resolver todas as instâncias do tipo I como um IEnumerable
(Array ou coleção não importa).
Em Windsor eu teria escrito o seguinte.
foreach(I i in container.ResolveAll<I>())
{
...
}
Eu estou migrando de Windsor para Autofac 1.4.4.561 mas não pode ver a sintaxe equivalente.
Solução
Para versons atuais de Autofac: (2.0 +, então qualquer coisa que você deve estar usando hoje)
Você registrar múltiplos ILoggers
(por exemplo):
var builder = new ContainerBuilder();
builder.Register<ConsoleLogger>()
.As<ILogger>();
builder.Register<EmailLogger>()
.As<ILogger>()
.PreserveExistingDefaults(); //keeps console logger as the default
Em seguida, obter todos os ILogger
s:
var loggers = container.Resolve<IEnumerable<ILogger>>();
Você não precisa fazer nada de especial, apenas pedir uma IEnumerable<T>
do tipo desejado. Autofac tem suporte coleção fora da caixa, juntamente com outras adaptadores que podem envolver seus componentes com funcionalidade adicional.
Este é o mesmo uso como o ImplicitCollectionSupportModule pré-2.x, mas cozido à direita.
Para versões antigas (0.x - 1.4)
Duas maneiras:
1) Use o registro de coleção
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>>();
Depois:
var loggers = container.Resolve<IEnumerable<ILogger>>();
que lhe dá uma IEnumerable.
ou 2) Você pode usar o módulo ImplicitCollectionSupport, o que tornará o trabalho código como versões mais recentes do Autofac:
builder.RegisterModule(new ImplicitCollectionSupportModule());
builder.Register(component1).As<ILogger>;
builder.Register(component2).As<ILogger>;
Em seguida, resolver uma coleção de ILogger ao invés de olhar para a resolução de todos.
var loggers = container.Resolve<IEnumerable<ILogger>>();
que lhe dá um IEnumerable, novamente.
Outras dicas
Uma atualização para o bem da nova versão (2.x). Tudo que você precisa agora é:
container.Resolve<IEnumerable<I>>();
Não há mais a necessidade de RegisterCollection()
ou ImplicitCollectionSupportModule
-. Essa funcionalidade sai da caixa