2010-03-07 7 views
6

considerar lo siguiente:Ninject 2.0: ¿vinculante a un objeto que utiliza la misma interfaz más de una vez?

public Something(IInterface concreteObjectOne, IInterface concreteObjectTwo) 
    { 
     this.concreteObjectOne = concreteObjectOne; 
     this.concreteObjectTwo = concreteObjectTwo; 
    } 

¿Cómo SET SET este tipo de unión con Ninject? Intentaría buscar en Google el término, pero como no estoy seguro de cómo se llama, no puedo, ni puedo encontrar nada en Wiki sobre esto.

Editar:

Creo que esto se llama convención basada unión, tal como se describe here. Sin embargo, esta documentación es para la versión 1.0 y 2.0 no tiene el método Only. Me gustaría que esto se logre sin atributos, usando la convención de nombres o algo similar.

Respuesta

9

Además del uso del método "Solo", el artículo sugiere otra solución al especificar diferentes atributos para los objetos inyectados.

Ejemplo:

public class ObjectOneAttribute : Attribute 
{ 

} 
public class ObjectTwoAttribute : Attribute 
{ 

} 

Entonces

public Something([ObjectOneAttribute] IInterface concreteObjectOne, [ObjectTwoAttribute] IInterface concreteObjectTwo) 
    { 
     this.concreteObjectOne = concreteObjectOne; 
     this.concreteObjectTwo = concreteObjectTwo; 
    } 

Y cuando se quiere obligar a la interfaz con el objeto concreto correcta, utilice el método "WhereTargetHas":

Bind<IInterface>().To<YourConcreteTypeOne>().WhereTargetHas<ObjectOneAttribute>(); 
Bind<IInterface>().To<YourConcreteTypeTwo>().WhereTargetHas<ObjectTwoAttribute>(); 

Actualización: solución sin utilizar atributos:
utilizar el método de "Si":

Bind<IInterface>().To<YourConcreteTypeOne>().When(r => r.Target.Name == "concreteObjectOne"); 
Bind<IInterface>().To<YourConcreteTypeTwo>().When(r => r.Target.Name == "concreteObjectTwo") 

;

+0

Prefiero no agregar atributos. El final del artículo muestra cómo hacer uso de las convenciones, p. el parámetro se llama X. Eso es lo que realmente busco. – Finglas

+0

@Finglas He actualizado con otra solución –

+0

Eso es excelente. Estuve cerca cuando estaba jugando para que esto funcione, pero estás en el lugar correcto. No tengo nada en contra de los atributos por cierto, solo encuentro en este escenario que es un desperdicio. Este tipo de configuración no es común en mi base de código, por lo que usar el método When es mucho más agradable. Aclamaciones. – Finglas

5

Si se me permite ofrecer alguna orientación general, en lugar de específica de Ninject sobre esto, le sugiero que reconsidere su diseño ligeramente. El constructor actual es vago porque no ofrece ninguna guía sobre qué implementación de IInterface va a dónde - me doy cuenta de que esto es solo una maqueta de su API real, y mientras que la API real puede ofrecer más ayuda al desarrollador humano en la forma de parámetros con un nombre adecuado, una máquina como un DI Container no puede inferir el uso correcto.

Muchos Contenedores DI ofrecen alguna forma de abordar dicha imprecisión, por ejemplo, proporcionando atributos que puede usar para asociar nombres (metadatos) con cada dependencia. AFAIR, Ninject tiene Inject atributos ...

Sin embargo, tener en cuenta un par de alternativas:

La primera alternativa es encapsular las dos instancias de interfaz similares en un objeto Parámetro, así:

public interface IParameterObject 
{ 
    IInterface ObjectOne { get; } 

    IInterface ObjectTwo { get; } 
} 

Ahora puede cambiar el constructor para tomar una instancia de IParameterObject en lugar de las dos instancias de interfaz.

public Something(IParameterObject po) 
{ 
    this.concreteObjectOne = po.ObjectOne; 
    this.concreteObjectTwo = po.ObjectTwo; 
} 

Esto significa que usted puede empujar la configuración de IParameterObject a la Composition Root.

Otra alternativa a considerar es si tiene sentido considerar el caso con dos casos como un caso especial de un diseño más general que se lleva a cualquier número de instancias. Esto no siempre puede ser el caso, pero si lo es, se puede cambiar el constructor para esto:

public Something(IEnumerable<IInterface> objects) 

yo preferiría personalmente ninguna de las sugerencias anteriores sobre cualquier cosa que utiliza características ninject, porque me obliga a hacer que la API sea más explícita en general, y por lo tanto más legible y mantenible.

+0

@Mark. Respondió ayer (gracias de nuevo) me movió a usar una fábrica para utilizar el patrón de diseño de estrategia para mis algoritmos enchufables. Las fábricas en cuestión ahora toman los dos objetos concretos, pero como estoy usando el patrón de estrategia, ambos son de la misma interfaz. Normalmente sin IOC escribiría un código como este y conectaría manualmente las dependencias. También hace que las pruebas unitarias sean fáciles. Si bien lo que sugirió funcionaría, de alguna manera siento que no es necesario. Con 2.0, parece que no puedo encontrar la forma correcta de hacer otra cosa que simplemente unir. – Finglas

+0

Lo suficiente - me alegro de que haya encontrado una solución :) –

Cuestiones relacionadas