2011-05-19 9 views
13

Con Ninject, ¿cómo se configura el kernel para que pueda definir qué valores del constructor están pasando en la creación de instancias de un objeto?Ninject que pasa en los valores del constructor

Tengo el siguiente configurado en un módulo:

Bind<IService1>() 
    .To<Service1Impl>() 
    .InSingletonScope() 
    .Named("LIVE"); 
Bind<IService2>() 
    .To<Service2Impl>() 
    .InSingletonScope() 
    .Named("LIVE") 
    .WithConstructorArgument(
     "service1", 
     Kernel.Get<IService1>("LIVE")); 

Service2Impl toma un parámetro de constructor IService1 pero quiero que esto viene del contenedor. También quiero tener enlaces con nombre ya que mi código se orientará a diferentes versiones en tiempo de ejecución.

Esto parece funcionar pero ¿es la manera correcta de lograr lo que quiero hacer? ¿Debo estar logrando sin el uso de enlaces nombrados y cableando diferentes módulos de configuración en el kernel?

EDITAR

He utilizado el método ToMethod() ahora para especificar un delegado para llamar a petición de un tipo específico. Esto parece un poco más agradable ya que obtendré advertencias de tiempo de compilación si la configuración del constructor es incorrecta en lugar de tener que saber el nombre del parámetro que estoy pasando primero.

Gracias

Respuesta

12

Al final utilicé ToMethod, lo que me permitió construir la instancia requerida con los constructores para mantener los errores de tiempo de compilación.

Por ejemplo:

.ToMethod(Func<IContext, T> method) 

Bind<IWeapon>().ToMethod(context => new Sword()); 
+1

Mucho prefiero esta sintaxis a .WithConstructorArgument, el compilador capta los errores de refactorización. +1 – gb2d

+1

¿Tenía en serio una aplicación que solicitara una interfaz de arma y un objeto de espada? – starmandeluxe

0

Tal vez los proveedores pueden ayudarlo. Enlace IService2 a un proveedor. y en el método Create de Provider, use Kernel.Get ("LIVE") para crear la instancia de Service2Impl.

ver el siguiente enlace para saber cómo utilizar Proveedor https://github.com/ninject/ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context

+0

Gracias, vi eso. Pensé que era demasiado código y como dice en el enlace que compartió, ToMethod es una versión más simple de un proveedor. –

16

Yo recomendaría la sobrecarga WithConstructorParameter que tiene una lambda de este modo:

Bind<IService2>() 
    .To<Service2Impl>() 
    .InSingletonScope() 
    .Named("LIVE") 
    .WithConstructorArgument(
     "service1", 
     ctx => ctx.Kernel.Get<IService1>("LIVE")); 

Esto asegurará que que la resolución de IServive1 sucede en el momento de la activación de Service2Impl y no en el inicio cuando se crea el contenedor. Mientras que en el caso de que en realidad no importa como Service1Impl es único, no puede haber efectos secundarios en hacerlo en la forma en que escribió originalmente:

  • La unión de dependencia que se inyecta por WithConstructorArgument tiene que ya existe. Esto implica que todas las consolidaciones tienen que hacerse en un orden particular. Esto crea puede ser complicado cuando hay múltiples módulos involucrados.

  • Pueden surgir problemas de ámbito cuando se utiliza el ámbito personalizado. Ninject 2.0 introdujo el caché y recolecta la administración del alcance, el enlace a una constante es muy probable que lo desordene.

5

Parece que estás mirando esto de la manera incorrecta. Ninject inyectará el servicio 1 automáticamente en el servicio 2 si lo tiene como argumento de constructor. No es necesario WithConstructorArgument en este caso.

Si hay varios IService1 debe ir por las condiciones. P.ej. WhenParentNamed (...)

0

creo ToConstant() es más limpio, el InSingletonScope es implícita:

Bind<IService2>().ToConstant(new Service2Impl(argument))) 
       .Named("LIVE"); 
Cuestiones relacionadas