2011-09-17 8 views
6

Siento que me falta algo obvio. He leído varias preguntas relacionadas aquí y he leído la página de enlaces contextuales actualizada en la wiki de Ninject, pero lamentablemente todavía no funciona.Enlace de ninject con el método de extensión WhenInjectedInto

Estoy tratando de actualizar una aplicación heredada que utilizó un patrón de fábrica para usar Ninject.

Tengo 1 interfaz (IInterface) implementada por 2 clases (ClassB y ClassC). IInterface tiene un método de carga. En el método de carga de ClassB, crea una instancia de ClassC y luego ejecuta su método de carga.

Básicamente, el flujo de programa es ClassA crea ClassB y ejecuta el método de carga. En el método de carga, ClassB crea ClassC que hace algo de trabajo.

Mis enlaces son de configuración como así ...

Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>(); 
Bind<IInterface>().To<ClassB>().WhenInjectedInto<ClassA>(); 

Cuando se ejecuta esta falla en el método de carga de ClassB con este error ...

error al activar IInterface No hay enlaces de juego están disponibles, y la el tipo no es autoblinable.

Si trato de la siguiente ...

Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>(); 
Bind<IInterface>().To<ClassB>(); 

Se hace un bucle sin fin y nunca crea ClassC.

EDITAR He simplificado esto en una unidad de prueba que pasa, pero no me da los resultados que quiero ...

[TestClass] 
public class NinjectTestFixture 
{ 
    private interface IDoSomething 
    { 
     void SaySomething(); 
    } 

    private class ClassA : IDoSomething 
    { 
     public void SaySomething() 
     { 
      Console.WriteLine("Hello from Class A"); 
     } 
    } 

    private class ClassB : IDoSomething 
    { 
     private IKernel _Kernel; 

     public ClassB(IKernel kernel) 
     { 
      _Kernel = kernel; 
     } 

     public void SaySomething() 
     { 
      Console.WriteLine("Hello from Class B"); 

      var x = _Kernel.Get<IDoSomething>(); 

      x.SaySomething(); 
     } 
    } 

    private class ClassC 
    { 
     private IKernel _Kernel; 

     public ClassC(IKernel kernel) 
     { 
      _Kernel = kernel; 
     } 

     public void SaySomething() 
     { 
      Console.WriteLine("Hello from Class C"); 

      var x = _Kernel.Get<IDoSomething>(); 

      x.SaySomething(); 
     } 
    } 

    [TestMethod] 
    public void TestMethod1() 
    { 
     var kernel = new StandardKernel(); 

     kernel.Bind<IDoSomething>().To<ClassA>(); 
     kernel.Bind<IDoSomething>().To<ClassB>().WhenInjectedInto<ClassC>(); 
     kernel.Bind<ClassC>().ToSelf(); 

     var x = kernel.Get<ClassC>(); 

     x.SaySomething(); 
    } 

La salida es: Hola de Clase C Hola de Clase A

Pero quiero: Hola de la Clase C hola de Clase B hola de Clase A

Gracias

Respuesta

6

Usted son no inyectar en ClassC. Estás pasando el kernel y resolviendo IDoSomething directamente desde él. Existe una gran diferencia.

No pase el kernel como parámetro, ya que no es Dependency Injection, es Service Location (buen artículo sobre la diferencia: Service Locator is an Anti-Pattern).

Cambio ClassC a ser:

private class ClassC  
{   
    private IDoSomething _doSomething;   
    public ClassC(IDoSomething doSomething) 
    {    
     _doSomething = doSomething;   
    }   

    public void SaySomething()   
    {    
     Console.WriteLine("Hello from Class C");    
     //var x = _Kernel.Get<IDoSomething>();    
     _doSomething.SaySomething();   
    }  
} 

También debe realizar los mismos cambios a Clase A ni ClassB (pasa el tipo/interfaz que desea resuelto, no el núcleo).

+0

Entiendo lo que dices, pero en el método SaySomething necesito crear una instancia de un objeto para que trabaje. En la misma clase hay otros métodos que crean instancias de métodos para hacer más trabajo. Si hiciera lo que está sugiriendo, tendría alrededor de 20 parámetros en mi constructor. El código fue escrito originalmente hace más de 6 años, así que estoy intentando actualizarlo con DI gradualmente.Me he atormentado mi cerebro sobre cómo hacer esto y pasar el kernel fue la solución más fácil que tuvo más sentido. Busqué una ubicación de servicio y eso no tenía sentido dado el código base actual. – oliwa

+0

Tu respuesta es correcta. Cuando hice los cambios que me propusieron obtuve los resultados que esperaba. – oliwa

+0

Entiendo lo que quiere decir: también yo he refactoreado los sistemas en los que tuve que usar algunos pasos interme- dios impares/desagradables para introducir DI. –

Cuestiones relacionadas