Autofac con più implementazioni della stessa interfaccia

Autofac con più implementazioni della stessa interfaccia

Per chiunque altro stia cercando, mi sono appena imbattuto in questo. Puoi usare il supporto implicito per IEnumerable. L'ho scritto per un uso futuro.

Fondamentalmente, puoi registrare i tipi di assembly per nome (o altri criteri) come IEnumerable che può essere utilizzato in seguito. La parte che preferisco di questo approccio è che puoi continuare ad aggiungere gestori di messaggi e finché ti attieni agli stessi criteri, non devi mai toccarli in seguito.

Registrazione AutoFac:

builder.RegisterAssemblyTypes(typeof (LoggingMessageHandler).Assembly)
  .Where(x => x.Name.EndsWith("MessageHandler"))
  .AsImplementedInterfaces();

Classe di consumo:

public class Foo
{
  private readonly IEnumerable<IMessageHandler> _messageHandlers

  public Foo(IEnumerable<IMessageHandler> messageHandlers)
  {
    _messageHandlers = messageHandlers;
  }

  public void Bar(message)
  {
    foreach(var handler in _messageHandlers)
    {
      handler.Handle(message)
    }
  }
}

Autofac ha il supporto per Decoratori.


4 opzioni qui:https://autofaccn.readthedocs.io/en/latest/faq/select-by-context.html

Opzione 1:riprogetta le tue interfacce

ILoggingMessageHandler , IDoSomethingMessageHandler 

Opzione 2:modifica le registrazioni

builder.Register(ctx => new FinalHandler(ctx.Resolve<LoggingMessageHandler >()));
or
builder.Register(ctx => new FinalHandler(ctx.Resolve<IDoSomethingMessageHandler >()));

Opzione 3:usa i servizi con chiave

builder.RegisterType<FinalHandler>()
           .WithParameter(
             new ResolvedParameter(
               (pi, ctx) => pi.ParameterType == typeof(IMessageHandler),
               (pi, ctx) => ctx.ResolveKeyed<ISender>("something")));

Opzione 4:usa i metadati

public class FinalHandler
{
  public FinalHandler([WithMetadata("sendBy", "something")] IMessageHandler messageHandler) { ... }
}