具有相同接口的多个实现的Autofac

Pet*_*ter 24 c# dependency-injection inversion-of-control autofac

我正在使用Autofac,并希望有多个接口实现.如何配置Autofac以便根据当前类型解析依赖关系?

更具体地说,我有一个接口和多个应该链接在一起的实现.

让我解释一下(虚拟课程):

public interface IMessageHandler
{
    void Handle(Message message);
}

public class LoggingMessageHandler : IMessageHandler
{
    private IMessageHandler _messageHandler;

    public LoggingMessageHandler(IMessageHandler messageHandler)
    {
        _messageHandler = messageHandler;
    }

    public void Handle(Message message) 
    {
        // log something
        _messageHandler.Handle(message);
    }
}

public class DoSomethingMessageHandler : IMessageHandler
{
    private IMessageHandler _messageHandler;

    public DoSomethingMessageHandler (IMessageHandler messageHandler)
    {
        _messageHandler = messageHandler;
    }

    public void Handle(Message message) 
    {
        // do something
        _messageHandler.Handle(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

链的底部可能是一个IMessageHandler不会将消息传递给下一个消息的链接.

如果我想要以下链:

TopLevelClass -> LoggingMessageHandler -> DoSomethingMessageHandler -> FinalHandler
Run Code Online (Sandbox Code Playgroud)

我怎么能告诉Autofac

  • 传递LoggingMessageHandlerTopLevelClass(以实现其依赖IMessageHandler)
  • 传递DoSomethingMessageHandlerLoggingMessageHandler(以实现其依赖IMessageHandler)
  • 传递LoggingMessageHandlerFinalHandler(以实现其依赖IMessageHandler)

它是否可能(我已经读过有关IEnumerable隐式支持)?或者我是否必须在中间使用额外的课程(工厂或其他)?

Kev*_* R. 17

对于其他人来说,我只是碰到了这个.您可以对IEnumerable使用隐式支持.我把它写下来以备将来使用.

基本上,您可以按名称(或其他条件)将程序集类型注册为IEnumerable,以后可以使用.我最喜欢的方法是你可以继续添加消息处理程序,只要你坚持相同的标准,你就不必再接触标准了.

Autofac注册:

builder.RegisterAssemblyTypes(typeof (LoggingMessageHandler).Assembly)
  .Where(x => x.Name.EndsWith("MessageHandler"))
  .AsImplementedInterfaces();
Run Code Online (Sandbox Code Playgroud)

消费类:

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)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Jim*_*lla 9

Autofac拥有装饰者支持.


Jai*_*der 7

这里有 4 个选项:https://autofaccn.readthedocs.io/en/latest/faq/select-by-context.html

选项 1:重新设计您的界面

ILoggingMessageHandler , IDoSomethingMessageHandler 
Run Code Online (Sandbox Code Playgroud)

选项 2:更改注册

builder.Register(ctx => new FinalHandler(ctx.Resolve<LoggingMessageHandler >()));
or
builder.Register(ctx => new FinalHandler(ctx.Resolve<IDoSomethingMessageHandler >()));
Run Code Online (Sandbox Code Playgroud)

选项 3:使用密钥服务

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

选项 4:使用元数据

public class FinalHandler
{
  public FinalHandler([WithMetadata("sendBy", "something")] IMessageHandler messageHandler) { ... }
}
Run Code Online (Sandbox Code Playgroud)