2010-02-11 20 views
8

Tengo una clase que tiene dependencias que he cableado con Ninject.Creación de kernel Ninject dentro de una biblioteca de clases

public interface IFoo {} 

public class MyObject { 
    [Inject] 
    IFoo myfoo; 
} 

En la implementación real estoy usando inyección de propiedades, pero solo para ilustrar rápidamente, voy a inyectar en el campo. Según tengo entendido, en lugar de casos de Newing MiObjeto, con el fin de obtener las dependencias que se inyecta correctamente, necesito utilizar

kernel.Get<MyObject>() 

Lo que estoy tropezando en la que sin embargo se MiObjeto sólo se utilizará en el contexto de una biblioteca de clase. La intención es que las aplicaciones finales creen sus propios módulos y los pasen a una instancia del kernel para hidratarse. Teniendo en cuenta que, ¿cuál es la forma más pragmática de acercar una instancia genérica de un kernel Ninject a mi biblioteca de clases para que las instancias de MyObject (y otros casos similares) puedan hidratarse?

Mi primera inclinación es una especie de factoría que internaliza un kernel singleton, que las aplicaciones mismas tienen que hidratar/inicializar cargando un módulo.

Así que en RandomService.cs

var myKernel = NinjaFactory.Unleash(); 
var myobj = myKernel.Get<MyObject>(); 
myobj.foo(); 

Antes de ir demasiado lejos por este camino, sin embargo, tengo que hacer una comprobación de validez para asegurarse de que el pensamiento es el sonido o que no hay alguna otra obvia Lo que me estoy perdiendo. Obviamente soy nuevo en IoC y siento que asimilo lo básico, pero no necesariamente las mejores formas de usarlo en el mundo real.

Respuesta

9

No estoy seguro de entender todos los detalles en su pregunta, pero por lo que tengo entendido, usted está preguntando cómo puede externalizar la dependencia en Ninject.

Es posible escribir DI-friendly libraries without ever referencing any particular DI Container (Ninject o cualquier otra cosa). Esto deja al consumidor de la biblioteca abierto para elegir el Contenedor DI de su agrado (o no usar un contenedor). Este enfoque es muy preferido porque proporciona un mayor grado de libertad.

Sin embargo, realmente deberías favorecer Constructor Injection sobre Property Injection. Aunque Property Injection parece engañosamente simple de implementar, en realidad es bastante difícil hacerlo bien.

Una de las grandes ventajas de Constructor Injection es que no necesita poner ningún atributo en el constructor porque estructuralmente ya contiene toda la información necesaria para que un Contenedor DI lo conecte correctamente.

+0

Afortunadamente, este es un lib interno (en sentido corporativo) así que tengo un público cautivo: otros desarrolladores en mi equipo, utilizando una herramienta estándar. Ahora, cada desarrollador puede tener enlaces diferentes que quieren, de ahí mi quandry original. Re: ctor vs prop injection, prop ciertamente parece tener una gran cantidad de cruft que tengo que escribir, pero me preocupa que la lista de dependencias crezca con el tiempo y por lo tanto las llamadas ctor. ¿Hay otras contras para la inyección de soporte que debería tener en cuenta? – bakasan

+2

Incluso con una aplicación interna, seguiría los mismos principios, ya que conducen a un código más limpio con una mejor separación de las preocupaciones. Hay muchos problemas potenciales con la Inyección de Propiedades, que incluye la protección de invariantes (¿es nula la dependencia?), Posiblemente intercambio en caliente de la dependencia inyectada (probablemente no sea algo que desee hacer) y una API más vaga en general. –

+2

Ah, y para ser directo y explícito al respecto: Considero Service Locator un anti-patrón: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx –

4

El punto de Mark es definitivamente mi punto de partida (de ahí un +1) sobre eso. NB no se olvide de seguir su enlace.

Por mi parte, he sido culpable en el pasado de renunciar al constructor por propiedades (o campos) demasiado pronto (mi "excusa" era que como clase base necesitaba 5 propiedades, no quería cargar todas las clases derivadas con eso La solución consistía en envolver las 5 propiedades involucradas en una clase o jerarquía de clases que representaran cualquier concepto subyacente que las propiedades representaran. Algo así como la refactorización de introducir parámetros de objetos.

Una buena discusión de las consideraciones que he encontrado útil es http://thinkbeforecoding.com/post/2009/05/15/IOC-container-go-hide (no puedo Busque el SO post que lo menciona y algunos temas en torno a ella, tal vez alguien le inyectará un enlace: D)

Otro blog que resume algunos de estos puntos es Your IoC Container is Showing

Y http://davybrion.com/blog/2009/11/integrating-your-ioc-container-with-agatha/

0

Aquí es una buena receta de propósito general para la búsqueda de todos los módulos ninject en el conjunto actual:

IKernel _serviceKernel = new StandardKernel(); 

Assembly myAssembly = this.GetType().Assembly; 

IEnumerable<Type> ninjectModuleTypes = 
    myAssembly.GetTypes().Where(type => type.BaseType == typeof(NinjectModule)); 

foreach (Type ninjectModuleType in ninjectModuleTypes) 
{ 
    NinjectModule mod = (NinjectModule)Activator.CreateInstance(ninjectModuleType); 
    _serviceKernel.Load(mod); 
} 
Cuestiones relacionadas