2009-03-06 2 views
6

sto cercando il seguente in Unity:Unità: come specificare di utilizzare un'istanza specifica di un tipo quando si risolve un altro tipo

Ho un tipo con la seguente costruttore

public Type1(Type2 firstDependency, Type3 secondDependency) 

Durante la risoluzione Type1 usando Unity, voglio specificare l'istanza specifica per Type2 da iniettare. Questa specifica istanza di Type2 non è registrata nel contenitore. Type3 è registrato nel contenitore e dovrebbe essere risolto come al solito.

Per essere più specifici, considerare Type1 è una classe DocumentViewer. Type2 è uno specifico Document. Type3 è un SpellingChecker.

Voglio essere in grado di risolvere DocumentViewer per un Document che è noto solo in fase di esecuzione. È possibile creare più istanze DocumentViewer per differenza Documents.

Come posso fare questo?

+0

Mi dispiace, ma non capisco perché non è possibile risolvere un'istanza della vista del documento con il codice indicato in delle risposte di seguito. Cosa significa "un documento è noto solo al runtime"? Se non si conosce il tipo esatto dell'istanza del documento, considerare l'utilizzo di interfacce. – Alexander

+0

Per dirlo in un altro modo: Voglio risolvere un tipo, ma solo lasciare che il contenitore risolva alcune delle dipendenze stesse. Voglio fornire io stesso le altre istanze. –

risposta

2

Ecco un rapido esempio che ho fatto, si utilizza registerInstance oppure è possibile utilizzare una gestione della durata Claas

static void Main(string[] args) 
{ 
    IUnityContainer container = new UnityContainer(); 

    container.RegisterType<Type1>(); 

    container.RegisterInstance<Type2>(new Type2()); 

    Type1 t = container.Resolve<Type1>(); 

    Type2 t2 = container.Resolve<Type2>(); 

    Type3 t3 = container.Resolve<Type3>(); 

    Console.ReadKey(); 
} 

public class Type1 
{ 
} 

public class Type2 
{ 
} 

public class Type3 
{ 
    private Type1 t; 
    private Type2 t2; 
    public Type3(Type1 t, Type2 t2) 
    { 
     this.t = t; 
     this.t2 = t2; 
    } 
} 

Aggiornamento: ho incluso un tipo con due parametri di costruttore per dimostrare che può anche essere risolto.

0

Non voglio registrare l'istanza di Type2 nel contenitore originale. L'istanza di tipo2 può essere diversa per le diverse istanze di Tipo1.

Il mio prossimo tentativo è di creare un contenitore figlio e registrare lì l'istanza specifica di Tipo2.

0

Provare a utilizzare le istanze denominate:

 

IUnityContainer container = new UnityContainer(); 
container.RegisterType<Type1>(); 
container.RegisterType<Type2>("Instance 1", new ContainerControlledLifetimeManager()); 
container.RegisterType<Type2>("Instance 2", new ContainerControlledLifetimeManager()); 
container.RegisterType<Type3>(); 

Type1 type1 = container.Resolve<Type1>(); 
if (type1 == ...) 
{ 
    Type2 instance1 = container.Resolve<Type2>("Instance 1"); 
} 
else 
{ 
    Type2 instance2 = ontainer.Resolve<Type2>("Instance 2"); 
} 

 

si può fare qualche controlli di tipo 1 e decidere quale tipo 2 è necessario. Si noti che la "nuova ContainerControlledLifetimeManager()" parametro inizializza un'istanza Singleton di tipo opposto resistenza, in modo da ottenere sempre la stessa istanza di tipo 2.

Aggiornamento: Lo stesso con le interfacce. Spero che questo ti aiuti.

 

IUnityContainer container = new UnityContainer(); 
container.RegisterType<TextDocument>(); 
container.RegisterType<ImageDocument>(); 
container.RegisterType(typeof (IView), typeof (TextView), "Text", new ContainerControlledLifetimeManager()); 
container.RegisterType(typeof (IView), typeof (ImageView), "Image", new ContainerControlledLifetimeManager()); 

IDocument document = container.Resolve<TextDocument>(); 

IView view = null; 
if (document is TextDocument) 
{ 
    view = container.Resolve<IView>("Text"); 
} 
else 
{ 
    view = container.Resolve<IView>("Image"); 
} 

view.Show(); 
 
+0

RegisterInstance raggiunge anche l'effetto Singleton –

0

Se si dispone di una classe con più costruttori, si può decidere che il costruttore viene utilizzato dal contenitore Unity utilizzando l'attributo "InjectionConstructor". Questo ti dà la possibilità di impostare alcuni parametri manualmente.

 

public class Test 
{ 
    public Test() 
    { 
    } 

    // Always use the following constructor 
    [InjectionConstructor] 
    public Test(Type1 type1) : this() 
    { 
    } 

    public Test(Type1 type1, Type2 type2) : this(type1) 
    { 
    } 
} 
 
0

Utilizzare una fabbrica.

public class Type1Factory 
{ 
    private Type3 type3; 

    public Type1Factory(Type3 _type3) 
    { 
    type3 = _type3; 
    } 

    public GetType1(Type2 type2) 
    { 
    return new Type1(type2, type3); 
    } 
} 

chiamata in questo modo:

// SpellingChecker is subclass of Type3 
IUnityContainer container = new UnityContainer(); 
container.RegisterType<Type3>(typeof(SpellingChecker)); 

// DocumentViewer is subclass of Type2 
Type1Factory factory = container.Resolve<Type1Factory>(); 
Type1 type1 = factory.GetType1(new DocumentViewer()); 

Questo presuppone che si sta solo cercando di utilizzare l'unità per risolvere la dipendenza Type3, e che non si ha il controllo dei costruttori in Type1. Se puoi modificare Type1, usa Alexader R.Il suggerimento di fare in modo che Unity risolva solo il costruttore di un parametro.

0

È possibile utilizzare la gerarchia del contenitore, si prega di leggere la mia risposta per la domanda simile qui: Microsoft Unity. How to specify a certain parameter in constructor?.

L'unica differenza è che è possibile utilizzare RegisterInstance() nel contenitore figlio anziché RegisterType(). E forse no, dipende dal fatto che tu abbia creato un'istanza prima o fuori dal tuo codice oppure no.