Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac with multiple implementations of the same interface

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

  • pass LoggingMessageHandler to TopLevelClass (to fulfill its dependency on IMessageHandler)
  • pass DoSomethingMessageHandler to LoggingMessageHandler (to fulfill its dependency on IMessageHandler)
  • pass 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)?

like image 348
Peter Avatar asked Mar 13 '14 16:03

Peter


People also ask

How do I register an Autofac interface?

Register by Type var builder = new ContainerBuilder(); builder. RegisterType<ConsoleLogger>(); builder. RegisterType(typeof(ConfigReader)); When using reflection-based components, Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container.

Why do we need Autofac?

AutoFac provides better integration for the ASP.NET MVC framework and is developed using Google code. AutoFac manages the dependencies of classes so that the application may be easy to change when it is scaled up in size and complexity. Let us peek into why the built-in DI container is being replaced by AutoFac.

What is Autofac container?

Autofac is an addictive IoC container for . NET. It manages the dependencies between classes so that applications stay easy to change as they grow in size and complexity. This is achieved by treating regular . NET classes as components.


1 Answers

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.

Autofac Registration:

builder.RegisterAssemblyTypes(typeof (LoggingMessageHandler).Assembly)   .Where(x => x.Name.EndsWith("MessageHandler"))   .AsImplementedInterfaces(); 

Consuming Class:

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)     }   } } 
like image 169
Kevin R. Avatar answered Sep 22 '22 21:09

Kevin R.