2016-12-29 6 views
1

私は着信メッセージが到着するとメッセージハンドラを作成するファクトリを持っています。メッセージハンドラには、着信メッセージに基づいて選択された設定オブジェクトやその他のインフラストラクチャコンポーネントなど、いくつかの依存関係があります。Autofac - 実行時情報を使用するファクトリを実装する方法は?

私は代理人と共にAutofacを使用していますが、私のMessageHandlerFactoryを特定の実装クラスに結合することを避けるのに問題があります。

// Handler defines a delegate that Autofac turns into a factory method 
public class FtpMessageHandler : IFtpMessageHandler { 
    public delegate FtpMessageHandler Factory (Configuration configuration); 

    public FtpMessageHandler(Configuration configuration, 
     S3Facade s3Facade, 
     .... other dependencies..... 
    ) 
    .... 
} 

// In Autofac module.. 

    // This is how I'd like to register the component, but it does NOT 
    // work - Autofac fails to resolve the delegate 
    builder.RegisterType<FtpMessageHandler>().As<IFtpMessageHandler>(); 

    // This is what DOES work  
    builder.RegisterType<FtpMessageHandler>(); 



public class MessageHandlerFactory { 
    public FtpMessageHandler.Factory FtpMessageHandlerFactory { get; } 
    ... 
    public MessageHandlerFactory(FtpMessageHandler.Factory ftpMessageHandlerFactory, ....) 

     FtpMessageHandlerFactory = ftpMessageHandlerFactory; 
    ) 

    public IMessageHandler GetMessageHandler(MessageTypeEnum type, Configuration config) { 
     if (type == MessageTypeEnum.FTP) 
      return FtpMessageHandlerFactory.Invoke(config); 
     .... 
    ) 
} 

だから......これはファッションの後、動作します:

は、ここで私は工場に代表団を注入することができました唯一の方法です。

しかし、私は具体的な型をMessageHandlerFactoryに注入しなければならないと不満です。たとえば、これは、ファクトリを変更せずにIMessageHandlerでデコレータを使用することを排除します。

これを行うより良い方法はありますか?アレックス・マイヤー - Gleavesによって記載

+0

applicatino成分にランタイムデータを注入することを防ぎます。それは[反パターン](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=99)です。 – Steven

+0

良い点。私の現在のソリューションでは、実行時データは、オブジェクト作成後にメソッドに渡されます。 –

答えて

0

Iのアプローチに基づいて、解決策を見つけたhttp://alexmg.com/selectively-resolving-services-at-runtime-with-autofac/

// New class 
public class MessageHandlerMetadata 
{ 
    public FileTransportTypeEnum TransportType { get; set; } 
} 


// Registration  
     builder.Register(c => new FtpMessageHandler(c.Resolve<IS3Facade>(), c.Resolve<IFtpHelper>())) 
      .As<IMessageHandler>() 
      .WithMetadata<MessageHandlerMetadata>(m => m.For(am => am.TransportType, FileTransportTypeEnum.FTP)); 

     .... 

     builder.Register(
      c => new MessageHandlerFactory(c.Resolve<IConfigurationProvider>(), 
       c.Resolve<IEnumerable<Lazy<IMessageHandler, MessageHandlerMetadata>>>())) 
      .As<IMessageHandlerFactory>(); 


// In the Factory 

    public MessageHandlerFactory(
     IEnumerable<Lazy<IMessageHandler, MessageHandlerMetadata>> messageHandlers) { ... } 


    private IMessageHandler GetHandlerByConfigurationType(FileTransportTypeEnum fileTransportType, 
     DestinationConfiguration configuration) 
    { 

     var lazy = MessageHandlers.FirstOrDefault(h => h.Metadata.TransportType == fileTransportType); 
     if (lazy == null) 
     { 
      throw new ArgumentException($"No handler is registered with File Transport type {fileTransportType}."); 
     } 
     var handler = lazy.Value; 
     handler.Configure(configuration); 
     return handler; 
関連する問題