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にどのように伝えることができますか
LoggingMessageHandler
をTopLevelClass
に渡します(IMessageHandler
への依存関係を満たすため)DoSomethingMessageHandler
をLoggingMessageHandler
に渡します(IMessageHandler
への依存関係を満たすため)LoggingMessageHandler
をFinalHandler
に渡します(IMessageHandler
への依存関係を満たすため)それも可能ですか?(私は IEnumerableの暗黙的なサポート について読んだことがありますか?)または、間に追加のクラス(ファクトリーまたは何か)を使用する必要がありますか?
Autofacは Decorators をサポートしています。
他の誰かを検索するために、私はこれに出くわしました。 IEnumerableの暗黙的なサポートを使用できます。 将来使用するために作成しました 。
基本的に、アセンブリタイプを名前(またはその他の条件)でIEnumerableとして登録し、後で使用できます。このアプローチの私のお気に入りの部分は、メッセージハンドラーを追加し続けることができ、同じ基準に固執している限り、後で基準を変更する必要がないことです。
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)
}
}
}
難しくありません。具象型を自己として登録し、実行中に解決できます。次に、トップレベルメッセージハンドラー(例では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();