2014-03-13 2 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 

이 어떻게 (LoggingMessageHandler

  • 패스 DoSomethingMessageHandler (IMessageHandler에 대한 의존도를 수행하기 위해) TopLevelClass

    • 패스 LoggingMessageHandler에 Autofac 말할 수를 IMessageHandler에 대한 의존성을 수행하기 위해)
    • 개 패스 LoggingMessageHandlerFinalHandler

    가 그것도 가능 (IMessageHandler에 대한 의존도를 충족하기 위해) (I은 implicit support for IEnumerable에 대해 읽고)? 아니면 그 사이에 여분의 수업을 사용해야합니까 (공장 또는 무언가)?

  • +0

    [Decorator Pattern (패턴 디자이너)] (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(); 
    
    관련 문제