I'm using Autofac and would like to have multiple implementations of an interface. How can I configure Autofac so to resolve dependencies based on the current type?
More specifically, I have one interface and multiple implementations that should be chained together.
Let me explain (fictitious classes):
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);
}
}
At the bottom of the chain might be an IMessageHandler
that doesn't pass the message on to the next one.
If I want the following chain:
TopLevelClass -> LoggingMessageHandler -> DoSomethingMessageHandler -> FinalHandler
How can I tell Autofac to
LoggingMessageHandler
to TopLevelClass
(to fulfill its dependency on IMessageHandler
)DoSomethingMessageHandler
to LoggingMessageHandler
(to fulfill its dependency on IMessageHandler
)LoggingMessageHandler
to FinalHandler
(to fulfill its dependency on IMessageHandler
)Is it even possible (I have read about the implicit support for IEnumerable)? Or will I have to use an extra class in between (a factory or something)?
For anyone else searching, I just ran across this. You can use implicit support for the IEnumerable. I wrote it up for future use.
Basically, you can register assembly types by name (or other criteria) as an IEnumerable which can be consumed later. My favorite part of this approach is that you can keep adding message handlers and as long as you stick to the same criteria, you never have to touch the criteria afterwards.
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)
}
}
}