2010-06-23 14 views
14

Considere el siguiente código.Inyectar arreglo de interfaces en Ninject

public interface IFoo { } 


public class Bar 
{ 
    public Bar(IFoo[] foos) { } 
} 


public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IFoo[]>().ToConstant(new IFoo[0]); 
     // ToConstant() is just an example 
    } 
} 


public class Program 
{ 
    private static void Main(string[] args) 
    { 
     var kernel = new StandardKernel(new MyModule()); 
     var bar = kernel.Get<Bar>(); 
    } 
} 

Cuando intento ejecutar el programa obtengo la siguiente excepción.

error al activar IFoo
No hay enlaces de juego están disponibles, y el tipo no es auto-enlazable. camino
Activación:
2) Inyección de dependencia IFoo en Foos de parámetros de constructor de tipo Bar
1) Solicitud de Bar

¿Cómo se puede inyectar/se unen a una matriz en Ninject?

Gracias por su tiempo.

Editar:
Mis importaciones de aplicaciones de datos que se crea por un componente de terceros. El proceso de importación aplica diferentes tipos de filtros (por ejemplo, implementaciones de diferentes interfaces de filtro). Las reglas para el filtrado cambian con bastante frecuencia, pero son demasiado complejas para ser realizadas con una configuración pura (y un filtro maestro).

Quiero hacer que agregar/editar filtros sea lo más fácil posible. Lo que tengo es un ensamblaje donde se encuentran todas las implementaciones de filtros. Intenté vincular cada interfaz de filtro con el siguiente método (que proporciona una instancia de cada implementación de ese tipo de filtro). Básicamente, quiero evitar la necesidad de cambiar mi módulo Ninject cuando agrego/elimino clases de filtro.

private IEnumerable<TInterface> GetInterfaceImplementations<TInterface>(IContext context) 
    { 
     return GetType().Assembly.GetTypes() 
      .Where(t => typeof (TInterface).IsAssignableFrom(t) && IsConcreteClass(t)) 
      .Select(t => Kernel.Get(t)).Cast<TInterface>(); 
    } 

Me siento un poco culpable en términos de eludir el mecanismo DI de los contenedores. ¿Es esto una mala práctica? ¿Hay una práctica común para hacer tales cosas?

Resolución:
utilizo una clase contenedora como bsnote sugirió.

Respuesta

7

Esto es en gran medida una reformulación de la respuesta de @ bsnote (que he + 1d) que puede ayudar a entender por qué funciona de esta manera.

Ninject (y otros marcos de DI/complemento) tienen dos instalaciones distintas:

  1. la noción de cualquiera de unirse a una sola aplicación ambigua de un servicio (Get)
  2. Una instalación que le permite a uno obtener un conjunto de servicios [que uno recoge a continuación, mediante programación o uno de los agregados a través de alguna manera] (GetAll/ResolveAll en Ninject)

Su código de ejemplo pasa a utilizar sy ntax que está asociado con 2. arriba. (p.ej., en MEF, se suelen utilizar las anotaciones [ImportMany] para dejar esto en claro)

Tendría que buscar en las muestras (mire la fuente, es realmente corta, limpia y fácil de seguir) para encontrar una solución a esto.

Sin embargo, como dice @bsnote, una forma de refactorización su requerimiento es para envolver la matriz, ya sea en un recipiente, o tener un objeto que pregunte por ella (es decir, un método de fábrica o escribe el constructo repositorio)

También puede ser útil para usted explicar cuál es su caso real: ¿por qué hay una matriz desnuda? Seguramente hay una colección de ítems que suplican ser encapsulados detrás de todo esto - ¿esta pregunta ciertamente no surge mucho?

EDITAR: Hay un conjunto de ejemplos de escaneo en las extensiones que imagino que atacarían muchas de las cosas que intentas hacer (en cosas como StructureMap, este tipo de cosas está más integrado, lo que obviamente tiene ventajas y contras).

Dependiendo de si está tratando de lograr la convención sobre la configuración o no, es posible que desee considerar pegar una interfaz de marcador en cada tipo de complemento. Entonces puede explícitamente Bind cada uno. Alternativamente, para CoC, puede realizar el ciclo de rutina ModuleLoad() sobre el conjunto de implementaciones que genere (es decir, un montón de Get s individuales) en su edición.

De cualquier manera, cuando usted tiene los múltiples registros en su lugar se puede sin problemas ambas 'solicitud' una T[] o IEnumerable<T> y obtener el conjunto completo. Si desea lograr esto de manera explícita (es decir, el Localizador de servicios y todo lo que esto implica, como en el caso, puede usar GetAll para procesarlos de forma que no esté haciendo el bucle implícito en la forma en que lo hizo.

No estoy seguro si usted ha hecho esta conexión o si me falta algo de cualquier manera, espero que le ha enseñado a pegar un código en preguntas como las que habla> 1000 palabras:. P

+0

he escogido este como la respuesta ya que es más detallada. Gracias (1) a bsno ¡Te, también! –

4

También fue un problema para mí. Ninject inyecta cada elemento de una matriz en lugar de la matriz misma, por lo que debe tener una asignación definida para el tipo de elementos de la matriz. En realidad, no hay posibilidad de mapear la matriz como un tipo con la versión actual de Ninject. La solución es crear un contenedor alrededor de la matriz. Lazy Lazy Class se puede usar, por ejemplo, si te conviene. O puede crear su propio contenedor.

9

Ninject soporta múltiples inyección que podría resolver su problema. https://github.com/ninject/ninject/wiki/Multi-injection

public interface IFoo { } 
public class FooA : IFoo {} 
public class FooB : IFoo {} 

public class Bar 
{ 
    //array injected will contain [ FooA, FooB ] 
    public Bar(IFoo[] foos) { } 
} 

public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IFoo>().To<FooA>(); 
     Bind<IFoo>().To<FooB>(); 
     //etc.. 
    } 
} 
Cuestiones relacionadas