2014-03-13 59 views
13

我正在使用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到

  • LoggingMessageHandlerTopLevelClass(履行其對IMessageHandler依賴)於LoggingMessageHandler
  • DoSomethingMessageHandler(以履行對其的依賴IMessageHandler
  • LoggingMessageHandlerFinalHandler(履行其對IMessageHandler依賴)

它甚至有可能(我看了一下implicit support for IEnumerable)?或者我需要在兩者之間使用額外的類(工廠或其他)?

+0

你所描述的是[裝飾模式](https://en.wikipedia.org/wiki/Decorator_pattern)。你的'LoggingMessageHandler'是一個裝飾器。 – Steven

回答

8

對於其他人的搜索,我只是跑過這個。您可以對IEnumerable使用隱式支持。 I wrote it up for future use

基本上,您可以通過名稱(或其他條件)將組件類型註冊爲稍後可以使用的IEnumerable。這種方法中我最喜歡的部分是,您可以不斷添加消息處理程序,只要您堅持相同的標準,您就不需要事後觸摸標準。

Autofac報名:

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

消費類:

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) 
    } 
    } 
} 
1

並不太難。您可以將具體類型註冊爲自己並在您繼續時解決它。那麼你的頂層消息處理程序(LoggingMessageHandler在你的例子)可以註冊界面,這將是你的TopLevelClass

這裏使用就是你要找的東西(假設你有FinalHandler一個默認的構造函數)

var builder = new ContainerBuilder(); 
builder.RegisterType<FinalHandler>().AsSelf().SingleInstance(); 
builder.Register(c => new DoSomethingMessageHandler(c.Resolve<FinalHandler>())).AsSelf().SingleInstance(); 
builder.Register(c => new LoggingMessageHandler(c.Resolve<DoSomethingMessageHandler>())).As<IMessageHandler>().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<TopLevelClass>().As<ITopLevelClass>().InstancePerOwned();