2011-01-17 17 views
6

Vedo un comportamento strano nel contenitore Unity, quando si lavora con due interfacce, che si registrano allo stesso decoratore. Un esempio di codice sarà più chiaro.Unity: registrazione dello stesso tipo per due interfacce

Ho la seguente gerarchia di classe:

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

e questo è il codice di registrazione:

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

Durante la risoluzione MiaClasse sto diventando un BaseInterfaceDecorator con Interface2Impl invece di Interface1Impl. Sembra strano per me. Puoi spiegare?

risposta

9

Sembra che l'ultima istruzione di iniezione per un dato tipo "a" vince. Se prendi una copia di Reflector e dai un'occhiata all'implementazione di UnityContainer.RegisterType (tipo, tipo, stringa, LifetimeManager, InjectionMember []), vedrai perché.

IMO, questo comportamento è un bug. Per lo meno, InjectedMembers.ConfigureInjectionFor (Type, string, InjectionMember []) dovrebbe generare un'eccezione invece di sostituire silenziosamente la precedente configurazione di iniezione. Tuttavia, dovrebbe davvero supportare ciò che stai tentando.

+0

Nel caso in cui questo non è chiaro per i lettori; Internamente Unity memorizza nella cache la Build Key del tipo 'to' (ad esempio 'TTo' in firme generiche). La prossima volta che risolvi un tipo 'TFrom', la Build Key per 'TTo' viene usata per eseguire build up. Questa chiave di build è anche associata a un gestore della durata e quindi Unity sembra utilizzare il lifetime manager utilizzato per la prima volta (in Build Up) per tutte le risoluzioni secondarie per TTo (indipendentemente dall'identità di TFrom.) Questo è un bug con Unity's Costruisci chiavi. La soluzione alternativa consiste nell'utilizzare le registrazioni denominate, che sconfigge il punto nella definizione delle identità di tipo covariante. –

2

Non so se aiuta. Probabilmente è troppo tardi per te ormai. Tuttavia, ciò è possibile se si utilizza la registrazione con nome, cioè si registra ciascun tipo da risolvere con un nome diverso.

Ad esempio:

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

Questa soluzione è valida, ma elimina lo scopo nell'utilizzo dei tipi covarianti nella registrazione. Unity fa presupporre che tutte le risoluzioni per "TTo" si riferiscano alla stessa configurazione/istruzioni per la creazione di un'istanza TTo. Quindi, vedrai problemi con Injection Parameters e Lifetime Management dove l'identità di TFrom dovrebbe risultare in un comportamento differente (diversi iniettori, differenti lifetime manager, ecc.) –

Problemi correlati