web-dev-qa-db-ja.com

同じインターフェースの複数の実装を持つAutofac

Autofacを使用していますが、インターフェイスの複数の実装が必要です。 Autofacを構成して、現在のタイプに基づいて依存関係を解決するにはどうすればよいですか?

より具体的には、1つのインターフェイスと、複数の実装を一緒にチェーンする必要があります。

説明してみましょう(架空のクラス):

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への依存関係を満たすため)
  • DoSomethingMessageHandlerLoggingMessageHandlerに渡します(IMessageHandlerへの依存関係を満たすため)
  • LoggingMessageHandlerFinalHandlerに渡します(IMessageHandlerへの依存関係を満たすため)

それも可能ですか?(私は IEnumerableの暗黙的なサポート について読んだことがありますか?)または、間に追加のクラス(ファクトリーまたは何か)を使用する必要がありますか?

23
Peter

Autofacは Decorators をサポートしています。

8
Jim Bolla

他の誰かを検索するために、私はこれに出くわしました。 IEnumerableの暗黙的なサポートを使用できます。 将来使用するために作成しました

基本的に、アセンブリタイプを名前(またはその他の条件)で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)
    }
  }
}
17
Kevin R.

難しくありません。具象型を自己として登録し、実行中に解決できます。次に、トップレベルメッセージハンドラー(例では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();
0
arviman