una que puede programacion poo interfaz interfaces instancia implementacion heredar declaracion declara cómo crear clase caracteristicas c# dependency-injection inversion-of-control autofac

c# - puede - que es una interfaz en programacion



Autofac con múltiples implementaciones de la misma interfaz. (3)

Autofac tiene soporte para Decorators .

Estoy usando Autofac y me gustaría tener varias implementaciones de una interfaz. ¿Cómo puedo configurar Autofac para resolver las dependencias basadas en el tipo actual?

Más específicamente, tengo una interfaz y varias implementaciones que deben estar encadenadas.

Déjame explicarte (clases ficticias):

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); } }

En la parte inferior de la cadena puede haber un IMessageHandler que no pasa el mensaje al siguiente.

Si quiero la siguiente cadena:

TopLevelClass -> LoggingMessageHandler -> DoSomethingMessageHandler -> FinalHandler

¿Cómo puedo decirle a Autofac que

  • pasar LoggingMessageHandler a TopLevelClass (para cumplir con su dependencia de IMessageHandler )
  • pasar DoSomethingMessageHandler a LoggingMessageHandler (para cumplir con su dependencia de IMessageHandler )
  • pasar LoggingMessageHandler a FinalHandler (para cumplir con su dependencia de IMessageHandler )

¿Es incluso posible (he leído sobre el soporte implícito para IEnumerable )? ¿O tendré que usar una clase extra entre (una fábrica o algo)?


No es muy difícil. Puede registrar tipos concretos como uno mismo y resolverlos a medida que avanza. Luego, su controlador de mensajes de nivel superior (LoggingMessageHandler en su ejemplo) puede registrarse para la interfaz, que será utilizada por su TopLevelClass

Esto es lo que está viendo (asumiendo que tiene un constructor predeterminado para 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();


Para alguien más buscando, acabo de encontrarme con esto. Puede utilizar el soporte implícito para el IEnumerable. Lo escribí para uso futuro .

Básicamente, puede registrar los tipos de ensamblaje por nombre (u otro criterio) como un IEnumerable que se puede consumir más adelante. Mi parte favorita de este enfoque es que puede seguir agregando manejadores de mensajes y siempre que cumpla con los mismos criterios, nunca tendrá que tocar los criterios después.

Registro autofac:

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

Clase de consumo:

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) } } }