2009-03-06 12 views
6

Estoy intentando lo siguiente en la Unidad:Unidad: cómo especificar el uso de instancia específica de un tipo en la resolución de otro tipo

tengo un tipo con el siguiente constructor

public Type1(Type2 firstDependency, Type3 secondDependency) 

Al resolver Type1 usando Unity, quiero especificar la instancia específica para Type2 para inyectar. Esta instancia específica de Type2 no está registrada en el contenedor. Type3 está registrado en el contenedor y debe resolverse como de costumbre.

Para ser más específicos, considere Type1 es una clase DocumentViewer. Type2 es un Document específico. Type3 es un SpellingChecker.

Quiero poder resolver DocumentViewer para un Document que solo se conoce en tiempo de ejecución. Se pueden crear varias instancias de DocumentViewer para differenct Documents.

¿Cómo puedo hacer esto?

+0

Lo siento, todavía no entiendo por qué no es posible resolver una instancia de su vista de documento con el código proporcionado en una de las respuestas a continuación. ¿Qué significa "un documento solo se conoce en tiempo de ejecución"? Si no conoce el tipo exacto de la instancia del documento, considere usar interfaces. – Alexander

+0

Para decirlo de otra manera: Quiero resolver un tipo, pero solo dejo que el contenedor resuelva algunas de las dependencias. Quiero proporcionar las otras instancias yo mismo. –

Respuesta

2

Aquí está un ejemplo rápido que he hecho, se utiliza registerInstance o puede utilizar un sistema de gestión por vida 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; 
    } 
} 

Actualización: que incluía un tipo con dos parámetros en el constructor para mostrar que también puede ser resuelto.

0

No deseo registrar la instancia de Type2 en el contenedor original. La instancia de type2 puede ser diferente para diferentes instancias de Type1.

Mi próximo intento es crear un contenedor hijo y registrar allí la instancia específica de Type2.

0

Intente utilizar las instancias con nombre:

 

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

 

Usted puede hacer algunas comprobaciones de tipo 1 y decidir qué instancia de tipo 2 que va a necesitar. Tenga en cuenta que el "nuevo ContainerControlledLifetimeManager()" parámetro inicializar una instancia singleton del tipo resistido, por lo que siempre obtendrá la misma instancia de tipo 2.

Actualización: Lo mismo pasa con las interfaces. Espero que esto ayude.

 

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 también logra el efecto Singleton –

0

Si usted tiene una clase con varios constructores, puede decidir qué constructor es usado por el contenedor de la unidad mediante el atributo "InjectionConstructor". Esto le da la posibilidad de configurar algunos parámetros de forma manual.

 

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

Utilice una fábrica.

public class Type1Factory 
{ 
    private Type3 type3; 

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

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

llamada de esta manera:

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

Esto supone que sólo está tratando de utilizar la Unidad resolver la dependencia de Tipo 3, y que no tiene ningún control sobre los constructores de Tipo 1. Si puedes editar Type1, usa Alexader R.La sugerencia de hacer que Unity solo resuelva el constructor de un parámetro.

0

Puede usar la jerarquía de contenedores, lea mi respuesta para una pregunta similar aquí: Microsoft Unity. How to specify a certain parameter in constructor?.

La única diferencia es que parece que debe usar RegisterInstance() en el contenedor de su hijo en lugar de RegisterType(). Y tal vez no, depende de si creó una instancia antes en algún lugar fuera de su código o no.

Cuestiones relacionadas