2009-09-08 15 views
36

¿Cómo registro dos interfaces diferentes en unidad con la misma instancia ... Actualmente estoy usandoUnidad Registro dos interfaces como un producto único

 _container.RegisterType<EventService, EventService>(new ContainerControlledLifetimeManager()); 
     _container.RegisterInstance<IEventService>(_container.Resolve<EventService>()); 
     _container.RegisterInstance<IEventServiceInformation>(_container.Resolve<EventService>()); 

que funciona, pero no se ven bien ..

Entonces, creo que entiendes la idea. EventService implementa dos interfaces, quiero una referencia al mismo objeto si resuelvo las interfaces.

Chris

+0

OK, si este es el camino a seguir, solo lo tengo. Simplemente estaba interesado si había una manera más elegante, pero está funcionando, y ese es el punto. Me gusta mucho Unity hasta ahora ... muy bien en combinación con PRISM –

+0

Eche un vistazo a la respuesta de Sven ... tiene mucho mérito. Mira los comentarios de @Chris Tavares en mi respuesta para más detalles. Compruébalo y si te gusta, te recomiendo que lo marques como la respuesta para otras personas. –

Respuesta

13

Editar

Después de algunos comentarios en los comentarios he decidido que la respuesta de Sven es una respuesta muy superior. Gracias a Chris Tavares por señalar los méritos técnicos.


Esa es prácticamente la única forma de hacerlo.

Se podría modificar ligeramente (odio RegisterType con el mismo tipo para cada parámetro genérico):

EventService es = _container.Resolve<EventService>(); 
_container.RegisterInstance<IEventService>(es); 
_container.RegisterInstance<IEventServiceInformation>(es); 

Si uno o más de sus hijos COI se va a solicitar el tipo concreto EventService (esperemos que no) agregaría uno más RegisterInstance del tipo RegisterInstance<EventService>. Esperemos que no lo necesite y todos los objetos dependientes piden un IEventService, en lugar de un EventService.

Espero que esto ayude, Anderson

+5

Es una buena práctica con la inyección de dependencia, separar el tiempo de cableado del tiempo de resolución tanto como sea posible. Esta solución tiene el inconveniente de que requiere que mezcle llamadas para 'resolver' con llamadas a 'registrar' –

+0

@Nigel Thorne: Generalmente eso es cierto, pero en este caso el OP tenía un servicio que necesitaba para registrar que tenía muchas dependencias. Le sugerí a Unity que creara este objeto para que esas dependencias se resolvieran automáticamente, de modo que la instancia se pudiera usar para ambas llamadas de registro (necesitaba la misma instancia para cada interfaz). Normalmente esto no es deseable, pero realmente es la única manera de hacer esto en este caso (que no sea instanciar el objeto manualmente). –

+3

Esto realmente no es el camino a seguir; en su lugar, utilice la respuesta de Sven Kunzler a continuación. –

51

[Editar]

La solución para hacer esto a través de la configuración de XML se puede encontrar here. Sobre la base de esa respuesta me gustaría proponer un enfoque de sólo código simplificado de la siguiente manera:

_container.RegisterType<IEventService, EventService>(new ContainerControlledLifetimeManager()); 
_container.RegisterType<IEventServiceInformation, EventService>(new ContainerControlledLifetimeManager()); 
bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>()); 

De esta manera, la propia clase EventService no se publica por el contenedor. Como la clase se debe considerar como un detalle de implementación, este es el enfoque preferible.

[Respuesta original]

Un poco tarde una respuesta, pero debe hacer el truco:

_container.RegisterType<EventService>(new ContainerControlledLifetimeManager()); 
_container.RegisterType<IEventService, EventService>(); 
_container.RegisterType<IEventServiceInformation, EventService>(); 

bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>()); 
+0

¿Alguien sabe cómo hacer esto a través de la configuración? – JML

+0

También me gustaría saber cómo hacer esto a través de la configuración. – lukebuehler

+6

Curiosamente, (al menos aquí) parece que al configurar uno de ellos para que sea un registro nombrado no funciona ... – Reddog

0

Una solución que también puede funcionar para las instancias con nombre es usar el adapter para crear los adaptadores desechables a la interfaz que envuelve las instancias de singleton. Entonces, las instancias resueltas siempre se dirigirán a la instancia singleton, evento si se resuelven usando ResolveAll. Esto ayuda al tener un montón de servicios que implementan una interfaz genérica como IStartable o algo así.

public class EventServiceAdapter<T> : IEventService where T : IEventService 
{ 
    private readonly T _adapted; 
    EventServiceAdapter(T adapted) 
    { 
     _adapted = adapted; 
    } 
    public string SomeMethod() 
    { 
     return _adapted.SomeMethod(); 
    } 
} 

A continuación, registre el adaptador de interfaz alrededor de su tipo de singleton registrado.

_container 
    .RegisterType<EventService>(new ContainerControlledLifetimeManager()) 
    .RegisterType<IEventService, EventServiceAdapter<EventService>>("namedEventService"); 

entonces usted puede ocultar cualquier Singleton detrás de cualquier número de interfaces, y el trabajo utilizando tanto Resolver y ResolveAll.

4

El enfoque del adaptador parecía voluminoso para algo tan simple, así que busqué un poco más. Para solucionar el problema con las instancias mencionadas, debe registrar el tipo y registrar las fábricas para las interfaces.

InjectionFactory factory = new InjectionFactory(x => x.Resolve<SimulationService>()); 
this.Container.RegisterType<SimulationService>(new ContainerControlledLifetimeManager()); 
this.Container.RegisterType<IContentProvider>("SimulationContentProvider", factory); 
this.Container.RegisterType<ISimulationService>(factory); 

De esta manera no es necesario crear una instancia de la clase concreta (en el registro), que no era posible en mi caso debido a las dependencias que faltan.

Cuestiones relacionadas