具有相同接口的多个实现的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
我怎么能告诉Autofac
- 将
LoggingMessageHandler
传递给TopLevelClass
(以实现其对IMessageHandler
依赖) - 将
DoSomethingMessageHandler
传递给LoggingMessageHandler
(以实现其对IMessageHandler
依赖) - 将
LoggingMessageHandler
传递给FinalHandler
(以实现其对IMessageHandler
依赖)
它是否可能(我已阅读有关IEnumerable的隐式支持 )? 或者我是否必须在中间使用额外的课程(工厂或其他)?
Autofac拥有装饰者支持。
对于其他人来说,我只是碰到了这个。 您可以对IEnumerable使用隐式支持。 我把它写下来以备将来使用 。
基本上,您可以按名称(或其他条件)将程序集类型注册为IEnumerable,以后可以使用。 我最喜欢的方法是你可以继续添加消息处理程序,只要你坚持相同的标准,你就不必再接触标准。
Autofac注册:
builder.RegisterAssemblyTypes(typeof (LoggingMessageHandler).Assembly) .Where(x => x.Name.EndsWith("MessageHandler")) .AsImplementedInterfaces();
消费类:
public class Foo { private readonly IEnumerable _messageHandlers public Foo(IEnumerable messageHandlers) { _messageHandlers = messageHandlers; } public void Bar(message) { foreach(var handler in _messageHandlers) { handler.Handle(message) } } }
不太难。 您可以将具体类型注册为self,并在进行时解决它。 然后可以为接口注册顶级消息处理程序(在您的示例中为LoggingMessageHandler),TopLevelClass将使用该接口
这是你正在看的东西(假设你有一个FinalHandler的默认构造函数)
var builder = new ContainerBuilder(); builder.RegisterType().AsSelf().SingleInstance(); builder.Register(c => new DoSomethingMessageHandler(c.Resolve ())).AsSelf().SingleInstance(); builder.Register(c => new LoggingMessageHandler(c.Resolve())).As().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().As().InstancePerOwned();