具有相同接口的多个实现的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); } } 

在链的底部可能是IMessageHandler ,它不会将消息传递给下一个消息。

如果我想要以下链:

 TopLevelClass -> LoggingMessageHandler -> DoSomethingMessageHandler -> FinalHandler 

我怎么能告诉Autofac

  • LoggingMessageHandler传递给TopLevelClass (以实现其对IMessageHandler依赖)
  • DoSomethingMessageHandler传递给LoggingMessageHandler (以实现其对IMessageHandler依赖)
  • LoggingMessageHandler传递给FinalHandler (以实现其对IMessageHandler依赖)

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

Autofac拥有装饰者支持。

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

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

Autofac注册:

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

消费类:

 public class Foo { private readonly IEnumerable _messageHandlers public Foo(IEnumerable messageHandlers) { _messageHandlers = messageHandlers; } public void Bar(message) { foreach(var handler in _messageHandlers) { handler.Handle(message) } } } 

不太难。 您可以将具体类型注册为self,并在进行时解决它。 然后可以为接口注册顶级消息处理程序(在您的示例中为LoggingMessageHandler),TopLevelClass将使用该接口

这是你正在看的东西(假设你有一个FinalHandler的默认构造函数)

 var builder = new ContainerBuilder(); builder.RegisterType().AsSelf().SingleInstance(); builder.Register(c => new DoSomethingMessageHandler(c.Resolve())).AsSelf().SingleInstance(); builder.Register(c => new LoggingMessageHandler(c.Resolve())).As().SingleInstance(); //now finally your top level class - this will automatically pick your LoggingMessageHandler since the others have been registered onto their concreteTypes only builder.RegisterType().As().InstancePerOwned();