Estoy bastante cómodo con la inyección de dependencia usando NInject en MVC3. Mientras trabajaba en una aplicación MVC3, desarrollé una fábrica de creación de controladores personalizada utilizando NInject, por lo que cualquier controlador que se cree tendrá dependencias inyectadas a través de esta fábrica de controladores.
Ahora estoy comenzando a desarrollar una aplicación de Windows, quiero usar la inyección de dependencia de toda la aplicación. es decir, cada objeto debe crearse a través de NInject, para facilitar las pruebas unitarias. Guíeme para asegurarme de que cada objeto creado debe ser a través de NInject Factory únicamente.
Por ejemplo, si en cualquier formulario de Windows en el Button_Click
evento escribo:
TestClass testClass = new TestClass()
y TestClass
tiene alguna dependencia, digamos, ITest
entonces debe resolverse automáticamente. Sé que puedo usar:
Ikernel kernel = new StandardKenel()
//AddBinding()
TestClass testClass = kenel.get<TestClass>();
Pero me resulta tedioso hacer esto cada vez que quiero crear un objeto. También obliga al desarrollador a crear el objeto de una manera particular. ¿Se puede mejorar?
¿Puedo tener un repositorio central para la creación de objetos y luego cada creación de objetos usará automáticamente ese repositorio?
fuente
Respuestas:
Para las aplicaciones cliente, a menudo es mejor adaptar un patrón como MVP (o MVVM) y utilizar el enlace de datos del formulario al ViewModel o Presentador subyacente.
Para los ViewModels, puede inyectar las dependencias requeridas utilizando la inyección de constructor estándar.
En la raíz de composición de su aplicación, puede conectar todo el gráfico de objetos para su aplicación. No necesita usar un contenedor DI (como Ninject) para esto, pero puede hacerlo.
fuente
Las aplicaciones de Windows Forms generalmente tienen un punto de entrada que se ve así:
Si hace de este punto en el código la raíz de su composición , puede reducir enormemente el número de lugares donde tiene código que invoca explícitamente a Ninject como si fuera un Localizador de servicios.
Desde este punto, inyecta todas sus dependencias mediante la inyección del constructor.
Si su "dependencia" es algo que necesita poder producir varias veces, entonces lo que realmente necesita es una fábrica:
Puede implementar la interfaz IFactory de esta manera para evitar tener que crear toneladas de implementaciones únicas:
fuente
InjectionFactory<T>
implementadas, entonces el código proporcionado debería funcionar bien. ¿Hay algo en particular con lo que tienes problemas?Type
, pero que garantizaría que los objetos que hidratara para esaType
implementación o extendieran un tipo genérico dado. Nada muy especialSiempre escribo un contenedor de Adaptador para cualquier Contenedor IoC, que se ve así:
Para Ninject, específicamente, la clase de adaptador concreta se ve así:
La razón principal para hacer esto es abstraer el marco de IoC, de modo que pueda reemplazarlo en cualquier momento, dado que la diferencia entre los marcos generalmente está en la configuración y no en el uso.
Pero, como beneficio adicional, las cosas también se vuelven mucho más fáciles para usar el marco de IoC dentro de otros marcos que no lo admiten de manera inadvertida. Para WinForms, por ejemplo, son dos pasos:
En su método Main, simplemente cree una instancia de un contenedor antes de hacer cualquier otra cosa.
Y luego tenga una Forma base, de la cual derivan otras formas, que llama Inyectar sobre sí misma.
Esto le dice a la heurística de cableado automático que intente inyectar recursivamente todas las propiedades en la forma que se ajuste a las reglas establecidas en sus módulos.
fuente
El buen uso de la inyección de dependencia generalmente se basa en separar el código que crea los objetos y la lógica comercial real. En otras palabras, no quisiera que mi equipo use
new
y cree con frecuencia una instancia de una clase de esa manera. Una vez hecho esto, no hay forma de cambiar fácilmente ese tipo creado por otro, ya que ya ha especificado el tipo concreto.Así que hay dos formas de solucionar esto:
TestClass
en su formulario de Windows para que ya tenga una instancia cuando la necesite. Cuando Ninject crea una instancia de su formulario, crea automáticamente la dependencia.IKernel
en su formulario de Windows y luego usarlo para crear una instanciaTestClass
. Dependiendo de su estilo, también hay otras formas de lograr esto (inyectando una clase de fábrica, delegado de fábrica, etc.).Hacer esto hace que sea fácil intercambiar tanto el tipo concreto de TestClass, como modificar la construcción real de la clase de prueba, sin modificar realmente el código que usa la clase de prueba.
fuente
No he usado Ninject, pero la forma estándar de crear cosas cuando está usando un IoC es hacerlo a través de
Func<T>
dondeT
es el tipo de objeto que desea crear. Entonces, si el objetoT1
necesita crear objetos de tipo,T2
entonces el constructor deT1
debe tener un parámetro de tipoFunc<T1>
que luego se almacena como un campo / propiedad deT2
. Ahora bien, cuando se desea crear objetos del tipoT2
enT1
que la invocaciónFunc
.Esto lo desacopla totalmente de su marco de IoC y es la forma correcta de codificar en una mentalidad de IoC.
La desventaja de hacer esto es que puede ser molesto cuando necesita cablear manualmente
Func
o, por ejemplo, cuando su creador requiere algún parámetro, por lo que IoC no puede conectarlo automáticamenteFunc
.http://code.google.com/p/autofac/wiki/RelationshipTypes
fuente