2009-03-06 6 views
6

J'essaie ce qui suit dans l'unité:Unité: comment spécifier utiliser instance spécifique d'un type lors de la résolution d'un autre type

J'ai un type avec le constructeur suivant

public Type1(Type2 firstDependency, Type3 secondDependency) 

Lors de la résolution Type1 en utilisant Unity, je veux spécifier l'instance spécifique pour Type2 à injecter. Cette instance spécifique de Type2 n'est pas enregistrée dans le conteneur. Type3 est enregistré dans le conteneur et doit être résolu comme d'habitude. Pour être plus précis, considérons Type1 est une classe DocumentViewer. Type2 est un Document spécifique. Type3 est un SpellingChecker.

Je veux être en mesure de résoudre DocumentViewer pour un Document qui est seulement connu au moment de l'exécution. Plusieurs instances DocumentViewer pour différencier Documents peuvent être créées.

Comment est-ce que je peux faire ceci?

+0

Désolé, je ne comprends toujours pas pourquoi il n'est pas possible de résoudre une instance de votre document avec le code donné dans les réponses ci-dessous. Que signifie "un document n'est connu qu'à l'exécution"? Si vous ne connaissez pas le type exact de l'instance de document, pensez à utiliser des interfaces. – Alexander

+0

Pour le dire d'une autre manière: Je veux résoudre un type, mais seulement laisser le conteneur résoudre lui-même certaines des dépendances. Je veux fournir les autres cas moi-même. –

Répondre

2

Voici un exemple rapide que je l'ai fait, vous utilisez RegisterInstance ou vous pouvez utiliser une gestion de vie 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; 
    } 
} 

Mise à jour: I inclus un type avec deux paramètres dans le constructeur de montrer qu'il peut aussi être résolu.

0

Je ne souhaite pas enregistrer l'instance de Type2 dans le conteneur d'origine. L'instance de type2 peut être différente pour différentes instances de Type1.

La prochaine tentative consiste à créer un conteneur enfant et à y enregistrer l'instance spécifique de Type2.

0

Essayez d'utiliser les instances nommées:

 

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

 

Vous pouvez faire des vérifications sur le type 1 et décider quel type 2 vous aurez besoin. Notez que le paramètre « nouveau ContainerControlledLifetimeManager() » initialise une instance singleton du type résisté, vous obtiendrez toujours la même instance de type 2.

Mise à jour: même avec des interfaces. J'espère que cela t'aides.

 

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 atteint également l'effet singleton –

0

Si vous avez une classe avec plusieurs constructeurs, vous pouvez décider de quel constructeur est utilisé par le conteneur unité en utilisant l'attribut « InjectionConstructor ». Cela vous donne la possibilité de définir certains paramètres manuellement.

 

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

Utilisez une usine.

public class Type1Factory 
{ 
    private Type3 type3; 

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

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

Appelez cette façon:

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

Cela suppose que vous essayez seulement d'utiliser l'unité pour résoudre la dépendance Type3, et que vous ne contrôlez pas les constructeurs à Type1. Si vous pouvez modifier Type1, utilisez Alexader R.La suggestion de Unity pour résoudre seulement le constructeur d'un paramètre.

0

Vous pouvez utiliser la hiérarchie de conteneur, veuillez lire ma réponse pour une question similaire ici: Microsoft Unity. How to specify a certain parameter in constructor?. La seule différence est que vous devez utiliser RegisterInstance() dans votre conteneur enfant au lieu de RegisterType(). Et peut-être pas, cela dépend si vous avez créé une instance avant quelque chose en dehors de votre code ou non.

Questions connexes