Pet*_*ter 24 c# dependency-injection inversion-of-control 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);
}
}
Run Code Online (Sandbox Code Playgroud)
链的底部可能是一个IMessageHandler不会将消息传递给下一个消息的链接.
如果我想要以下链:
TopLevelClass -> LoggingMessageHandler -> DoSomethingMessageHandler -> FinalHandler
Run Code Online (Sandbox Code Playgroud)
我怎么能告诉Autofac
LoggingMessageHandler给TopLevelClass(以实现其依赖IMessageHandler)DoSomethingMessageHandler给LoggingMessageHandler(以实现其依赖IMessageHandler)LoggingMessageHandler给FinalHandler(以实现其依赖IMessageHandler)它是否可能(我已经读过有关IEnumerable的隐式支持)?或者我是否必须在中间使用额外的课程(工厂或其他)?
Kev*_* R. 17
对于其他人来说,我只是碰到了这个.您可以对IEnumerable使用隐式支持.我把它写下来以备将来使用.
基本上,您可以按名称(或其他条件)将程序集类型注册为IEnumerable,以后可以使用.我最喜欢的方法是你可以继续添加消息处理程序,只要你坚持相同的标准,你就不必再接触标准了.
builder.RegisterAssemblyTypes(typeof (LoggingMessageHandler).Assembly)
.Where(x => x.Name.EndsWith("MessageHandler"))
.AsImplementedInterfaces();
Run Code Online (Sandbox Code Playgroud)
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里有 4 个选项:https://autofaccn.readthedocs.io/en/latest/faq/select-by-context.html
选项 1:重新设计您的界面
ILoggingMessageHandler , IDoSomethingMessageHandler
Run Code Online (Sandbox Code Playgroud)
选项 2:更改注册
builder.Register(ctx => new FinalHandler(ctx.Resolve<LoggingMessageHandler >()));
or
builder.Register(ctx => new FinalHandler(ctx.Resolve<IDoSomethingMessageHandler >()));
Run Code Online (Sandbox Code Playgroud)
选项 3:使用密钥服务
builder.RegisterType<FinalHandler>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IMessageHandler),
(pi, ctx) => ctx.ResolveKeyed<ISender>("something")));
Run Code Online (Sandbox Code Playgroud)
选项 4:使用元数据
public class FinalHandler
{
public FinalHandler([WithMetadata("sendBy", "something")] IMessageHandler messageHandler) { ... }
}
Run Code Online (Sandbox Code Playgroud)