2010-12-16 12 views
6

Estoy probando Ninject con una aplicación de winforms (básicamente un boceto, lo estoy usando como un kata, pero nada tan riguroso o específico) en .net 4.Ninject for winforms: ¿mi arquitectura lo hace inútil?

Para crear el formulario principal, Estoy haciendo algo como:

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     [...] 
     IKernel kernel = BuildKernel(); 
     Application.Run(kernel.Get<frmMain>()); 
    } 

    static IKernel BuildKernel() 
    { 
     var modules = new INinjectModule[] 
     { 
      [..modules] 
     }; 

     return new StandardKernel(modules); 
    } 
} 

Fino. Esto crea una forma principal y la muestra muy bien, pasando las implementaciones de interfaz apropiadas al constructor inyectado.

¿Ahora qué? Mi aplicación es un MDI y tendrá varias ventanas secundarias para manipular el modelo de la aplicación. Ya no tengo una referencia al kernel, entonces ¿cómo se supone que debo Get() estos formularios? La respuesta obvia es "pasar el núcleo a la forma", supongo, pero esa es una estrategia horriblemente desordenada y estoy seguro de que no encaja en la filosofía de DI.

Voy a señalar aquí que la documentación para Ninject 2 es una mierda. Todo lo que puedo encontrar repite los ejemplos básicos, sin explicar realmente cómo DI usando Ninject hace que todo sea más fácil. El estándar de ejemplo dado no es lo suficientemente complicado como para hacer que valga la pena codificar y crear módulos y enlaces.

edición # 1:

Habiendo estudiado los enlaces amablemente proporcionados por Sam Holder, estoy probando el enfoque de 'composición de la raíz'. Mi arquitectura ahora obliga a todas las formas que utiliza para derivar de una CompositedForm con semántica constructor así:

[Inject] 
    public CompositingForm(ICompositionRoot CompositionRoot) 
    { 
     InitializeComponent(); 
     this.CompositionRoot = CompositionRoot; 
    } 
    public readonly ICompositionRoot CompositionRoot; 

    public CompositingForm() : this(new DummyCompositionRoot()) { } 

El segundo constructor es para el beneficio del Diseñador de formularios, que es estúpida y no puede entender la forma de marcas menos usted proporciona un constructor vacío. Ahora, cada formulario creado usando IKernel.Get<AForm>() tendrá (debería) una raíz de composición inyectada en él.

Entonces, como soy un alumno lento, ahora la pregunta es realmente '¿Qué debería ir en esta raíz de composición'?

Respuesta

1

Gracias a João Almeida y Kellabyte he encontrado un método que es más o menos satisfactoria:

  • definir un atributo personalizado que expone cualesquiera que sean las reglas de negocio que le interesan;
  • Define una implementación de IInjectionHeuristic que reconoce este atributo;
  • Usa un ViewModelLocator para cargar módulos en el kernel ninject.
5

¿No puedes pasarle una fábrica por crear los formularios hijos al constructor de formularios, y el formulario usa esto para obtenerlos, entonces ninject conectará la dependencia de fábrica cuando se crea el formulario usando get?

Creo que deberías configurar todo en la raíz de la aplicación usando el contenedor DI y después de eso el contenedor no debería ser necesario, pero realmente no he usado contenedores DI enfadados, y no NInject en absoluto, así que voy en lo que he leído ...

This answer puede ayudar a

+0

Gracias, ahora estoy haciendo un rastreo de enlaces desde esa publicación. Tal vez asimile todo el asunto un poco mejor. –

2

Nota: no sé mucho acerca de Ninject pero trabajé con Spring.net que es mucho más complicado. Los principios detrás deberían ser algo similar.

La respuesta de Sam Holder es excelente si tiene varios objetos de un tipo (inyectado) para crear (por ejemplo, CustomerOrderItem).

Si solo quiere cablear su forma principal, sugeriría que su constructor mdi-frmMain obtenga los parámetros para cada ventana hija que debe contener y deje que Ninject cree e inserte las ventanas secundarias. De esta forma, no es necesario hacer referencia a NInject fuera del "Programa de clase ". Esto se llama Constructor-Inyección.

Alternativamente, puede agregar un método al formulario que le agrega una página a mdi (MethodInjection).

static void Main() 
{ 
    [...] 
    IKernel kernel = BuildKernel(); 
    var main = kernel.Get<frmMain>(); 
    main.AddClientForm(kernel.Get<CustomerForm>()) ; 
    main.AddClientForm(kernel.Get<InvoiceForm>()) ; 
    Application.Run(main); 
} 
+0

Gracias por la entrada. Una pregunta: si voy a usar la inyección de constructor en frmMain, ¿cómo es posible decorar el constructor con [Inject] si solo quiero que 'clase Program' tenga una dependencia en Ninject? –

+0

Supongo que tiene un constructor para frmMain que toma una matriz de Childwindows. En BuildKernel() tiene una regla sobre cómo crear esta matriz y el resto debe hacer NInject. Por favor perdonen que no tengo un ejemplo de concreate ya que nunca he usado NInject todavía. – k3b