2011-01-17 18 views
6

Estoy viendo un comportamiento extraño en el contenedor de Unity, cuando se trabaja con dos interfaces, que ambas registran en el mismo decorador. Un ejemplo de código será más claro.Unity: registrando el mismo tipo para dos interfaces

que tienen la siguiente jerarquía de clases:

public interface IBaseInterface 
    { 

    } 

    public interface IInterface1: IBaseInterface 
    { 

    } 
    public interface IInterface2: IBaseInterface 
    { 

    } 
    public class Interface1Impl : IInterface1 
    { 
    } 
    public class Interface2Impl : IInterface2 
    { 
    } 

    public class BaseInterfaceDecorator: IInterface1,IInterface2 
    { 
     private readonly IBaseInterface baseInterface; 

     public BaseInterfaceDecorator(IBaseInterface baseInterface) 
     { 
      this.baseInterface = baseInterface; 
     } 
    } 

    public class MyClass 
    { 
     private readonly IInterface1 interface1; 

     public MyClass(IInterface1 interface1) 
     { 
      this.interface1 = interface1; 
     }    
    } 

Y este es el código de registro:

var container = new UnityContainer();   
     container.RegisterType<IInterface1, BaseInterfaceDecorator>(
      new InjectionConstructor(
       new ResolvedParameter<Interface1Impl>())); 

     container.RegisterType<IInterface2, BaseInterfaceDecorator>(
      new InjectionConstructor(
       new ResolvedParameter<Interface2Impl>())); 


     var dependency = container.Resolve<MyClass>(); 

Al resolver MiClase estoy un BaseInterfaceDecorator con Interface2Impl en lugar de Interface1Impl. Me parece extraño. ¿Puedes explicar?

Respuesta

9

Parece que la última instrucción de inyección para un tipo dado "a" gana. Si toma una copia de Reflector y echa un vistazo a la implementación de UnityContainer.RegisterType (Tipo, Tipo, cadena, LifetimeManager, InjectionMember []), verá por qué.

IMO, este comportamiento es un error. Como mínimo, InjectedMembers.ConfigureInjectionFor (Type, string, InjectionMember []) debería lanzar una excepción en lugar de reemplazar silenciosamente la configuración de inyección anterior. Sin embargo, realmente debe apoyar lo que estás intentando.

+0

En caso de que no está claro para los lectores; Internamente, Unity almacena en caché la clave de compilación del tipo 'para' (por ejemplo, 'TTo' en firmas genéricas). La próxima vez que resuelva un tipo de 'TFrom', la clave de compilación para 'TTo' se utiliza para realizar compilación. Esta clave de compilación también está asociada con un administrador de por vida y, por lo tanto, Unity parece usar el administrador de por vida utilizado por primera vez (en Build Up) para todos los resuelve subsiguientes para TTo (independientemente de la identidad de TFrom). Este es un error con Unity Build Keys. La solución consiste en utilizar registros con nombre, lo que anula el punto de establecer identidades de tipo covariantes. –

2

No sé si esto ayuda. Es muy probable que ya sea demasiado tarde para ti. Pero esto se puede lograr si usa el registro con nombre, es decir, si registra cada tipo para que se resuelva con un nombre diferente.

Por ejemplo:

Container.RegisterType<IInterface1, BaseInterfaceDecorator>("interface1"); 
Container.RegisterType<IInterface2, BaseInterfaceDecorator>("interface2"); 
+0

Esta es una solución válida, pero no permite el uso de tipos covariantes en el registro. Unity hace la suposición de que todos los resuelve para 'TTo' se refieren a la misma configuración/instrucciones para crear una instancia de TTo. Por lo tanto, verá problemas con los Parámetros de inyección y la Administración de por vida, donde la identidad de TFrom debería dar como resultado un comportamiento diferente (diferentes parms de inyección, diferentes administradores de por vida, etc.) –

Cuestiones relacionadas