2010-04-26 18 views
14

¿Cómo manejo las clases con métodos estáticos con Ninject?¿Cómo manejo las clases con métodos estáticos con Ninject?

Es decir, en C# uno no puede tener métodos estáticos en una interfaz, y Ninject funciona en base al uso de interfaces.

Mi caso de uso es una clase en la que me gustaría que tuviera un método estático para crear una instancia despoblada de .

EDIT 1

Sólo para añadir un ejemplo de la clase TopologyImp, en los GetRootNodes método(), ¿cómo iba a crear algunas clases INODE para volver? ¿Construiría estos con práctica de código normal o de alguna manera usaría Ninject? Pero si uso el contenedor para crear, ¿entonces no le he dado a esta biblioteca el conocimiento del COI?

public interface ITopology 
{ 
    List<INode> GetRootNodes(); 
} 


public class TopologyImp : ITopology 
{ 
    public List<INode> GetRootNodes() 
    { 
     List<INode> result = new List<INode>(); 

     // Need code here to create some instances, but how to without knowledge of the container? 
     // e.g. want to create a few INode instances and add them to the list and then return the list 
    } 
} 

public interface INode 
{ 
    // Parameters 
    long Id { get; set; } 
    string Name { get; set; } 
} 

class NodeImp : INode 
{ 
    public long Id 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 

    public string Name 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 
} 


// Just background to highlight the fact I'm using Ninject fine to inject ITopology 
public partial class Form1 : Form 
{ 
    private ITopology _top; 
    public Form1() 
    { 
     IKernel kernal = new StandardKernel(new TopologyModule()); 
     _top = kernal.Get<ITopology>(); 
     InitializeComponent(); 
    } 
} 

Respuesta

9

Si usted está construyendo un único o algo de esa naturaleza y tratando de inyectar dependencias, por lo general usted en lugar de escribir el código como una clase normal, sin tratar de poner en un montón de (probablemente incorrecto) código de la gestión de la singleton y, en su lugar, registrar el objeto InSingletonScope (v2 - no mencionó su versión de Ninject). Cada vez que haces eso, tienes una clase menos que no muestra sus dependencias.

Si se siente con una mente especialmente sangrienta y está seguro de que desea ir en contra de ese flujo general, las herramientas principales que Ninject le da es Kernel.Inject, que puede usar después de que usted (u otra persona) tenga new d up una instancia para inyectar las dependencias. Pero luego, para ubicar el Kernelm de uno, normalmente usará un Localizador de servicios, que probablemente causará tanto desorden como sea probable que se resuelva.

EDIT: Gracias por seguir - Veo lo que está buscando. Aquí está una manera hacky para aproximar the autofac automatic factory mechanism: -

/// <summary> 
/// Ugly example of a not-very-automatic factory in Ninject 
/// </summary> 
class AutomaticFactoriesInNinject 
{ 
    class Node 
    { 
    } 

    class NodeFactory 
    { 
     public NodeFactory(Func<Node> createNode) 
     { 
      _createNode = createNode; 
     } 

     Func<Node> _createNode; 
     public Node GenerateTree() 
     { 
      return _createNode(); 
     } 
    } 

    internal class Module : NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<Func<Node>>().ToMethod(context =>() => Kernel.Get<Node>()); 
     } 
    } 

    [Fact] 
    public void CanGenerate() 
    { 
     var kernel = new StandardKernel(new Module()); 
     var result = kernel.Get<NodeFactory>().GenerateTree(); 
     Assert.IsType<Node>(result); 
    } 
} 

El material ToMethod es una aplicación específica del patrón ToProvider - aquí está cómo se haría lo mismo por esa vía: -

... 

    class NodeProvider : IProvider 
    { 
     public Type Type 
     { 
      get { return typeof(Node); } 
     } 
     public object Create(IContext context) 
     { 
      return context.Kernel.Get<Node>(); 
     } 
    } 

    internal class Module : NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<Func<Node>>().ToProvider<NodeProvider>(); 
     } 
    } 

    ... 

Sin embargo, no he pensado en esto y no estoy recomendando esto como Una buena idea: puede haber formas mucho mejores de estructurar algo como esto. @Mark Seemann? : P

creo la Unidad y el MEF también apoyan las cosas en esta dirección (palabras clave: fábrica automática, func)

EDIT 2: sintaxis más corta si usted está dispuesto a utilizar atributos específicos del contenedor y colocar a la inyección de la propiedad (incluso si Ninject le permite anular los atributos específicos, me gusta mucho más la inyección de constructor):

class NodeFactory 
    { 
     [Inject] 
     public Func<Node> NodeFactory { private get; set; } 
     public Node GenerateTree() 
     { 
      return NodeFactory(); 
     } 
    } 

Datos 3: también es necesario tener en cuenta this Ninject Module by @Remo Gloor which is slated to be in the 2.4 release

EDITAR 4: también se superponen, pero no dir ectly relevante es el hecho de que en Ninject, puede solicitar un IKernel en su ctor/properties y tenerlo inyectado (pero eso no funciona directamente en un método estático).

+0

Hola Ruben: He agregado algunas aclaraciones a la pregunta. ¿Cómo crearías las instancias de INode en este caso? (es decir.ver este punto en el código que he comentado) - gracias – Greg

+0

@Greg: ¿Esto está bien? –

+0

Gracias Ruben- Tendré que dejar que esto se traduzca. Estoy reflexionando acerca de los beneficios tangibles que este enfoque realmente tendría sobre crear las clases normalmente en el lugar que indiqué en mi código. ¿Ves uno? Al igual que realmente rompería el concepto de COI al observar en todas las demás áreas de su código, ¿siguió el enfoque de Ninject? – Greg

Cuestiones relacionadas