2010-02-24 5 views
6

Espero que Peter o Ruben vean esta pregunta, ya que parecen ser los chicos con respecto a Ninject. Necesitaba crear un proveedor personalizado porque tengo una clase que toma 4 argumentos. Los dos se pueden inyectar porque son tipos, pero los otros dos son parámetros de configuración y son enteros. Se refieren a tiempos de espera en milisegundos.Usando Ninject, si creo un proveedor personalizado, ¿debo garantizar una sola instancia o puedo usar el atributo SingleInstance?

[SingleInstance] 
MyClass 
{ 
    ISomething something; 
    IOther other; 
    int timeout; 
    int delay; 

    [Inject] 
    MyClass(ISomething something, IOther other, int timeout, int delay) 
    { 
     this.something = something; 
     this.other = other; 
     this.timeout = timeout; 
     this.delay = delay; 
    } 
}  

Yo confiaba previamente en una fábrica que había creado para obtener los ajustes de configuración de tiempo de espera y de demora y para inyectar algo y otra. Ahora parece hacerlo bien, tendría que crear mi propio proveedor personalizado. Con lo que estoy de acuerdo.

Un par de puntos de puntos extra:

  1. Sé que podría utilizar la inyección de los parámetros . Pero eso crea una API engañosa . Los objetos deben ser devueltos en un estado listo para usar y sin esos 4 argumentos, no está listo para usar.
  2. El mismo argumento aplica al método de inyección.

Por lo tanto, mis preguntas finales:

  • ¿Eso significa que estoy en control de asegurar la única instancia de nuevo o a Ninject todavía cuidar de él a través de la [SingleInstance] atribuir?
  • ¿No debería volver a cambiar a la fábrica que tenía? ¿Qué gano al usar Ninject en este caso?

ACTUALIZACIÓN: Ejemplo de código conforme a lo solicitado

A continuación, el profesional Asumo le gustaría algo como esto:

class MyClassProvider : SimpleProvider<MyClass> { 
protected override MyClass CreateInstance(IContext context) { 
    int timeout= ConfigurationManager.AppSettings.Get("timeout"); 
    int delay= ConfiguraionManager.AppSettings.Get("delay"); 
    ISomething something = new SomethingImpl(); 
    IOther other = new OtherImpl(); 
    MyClass newOne = New MyClass(something, other, timeout, delay); 
    } 
} 

Pero debido a que ahora estoy utilizando un proveedor tiene mecanismos que la circunvalación de ninject de asegurar solamente se crea una sola instancia del objeto así que tengo que recurrir a:

class MyClassProvider : SimpleProvider<MyClass> { 

    protected static readonly MyClass myClassInstance; 
    private static object locker = new object(); 

    protected override MyClass CreateInstance(IContext context) { 
     if (myClassInstance == null) 
     { 
      lock (locker) 
      { 
       int timeout = ConfigurationManager.AppSettings.Get("timeout"); 
       int delay = ConfiguraionManager.AppSettings.Get("delay "); 
       ISomething something = new SomethingImpl(); 
       IOther other = new OtherImpl(); 
       MyClass newOne = New MyClass(something, other, timeout, delay); 
      } 
      return MyClassInstance 
     } 
     return myClassInstance 
    } 
} 

¿Hay algo th ¿Me estoy perdiendo?

+0

Parece que desea una respuesta específica de Ninject, pero también considere hacer que su código sea menos dependiente de un contenedor específico, y más expresivo en general: http://stackoverflow.com/questions/2045904/dependency-inject-di- friendly-library/2047657 # 2047657 Específicamente, es posible que Abstract Factory sea un patrón útil para aplicar en este caso. –

+0

Hola Actualmente estoy usando el patrón Abstract Factory. Sí, es muy específico para Ninject. Estoy usando Ninject para la inyección de dependencia. Tal vez debería ponerlo en el título, pero pensé que la etiqueta era suficiente. Editará el título ahora. – uriDium

+1

La etiqueta estaba bien, y entendí que preguntaste específicamente sobre Ninject. Esa fue la razón por la que puse mi comentario como un comentario, y no como una respuesta "correcta" :) –

Respuesta

1

Para ser honesto, tengo problemas para entender su pregunta, tal vez una muestra de código de cómo la cree podría ser útil (aunque su pregunta en general está bien redactada). Pero aquí hay una puñalada.

No estoy seguro de lo que quiere decir con SingleInstance - ¿de dónde es? (De hecho, no estaba al tanto de SingletonAttribute en v1, pero veo que no está en 2.0 Core). Si bien tiene sentido en algunos escenarios, definitivamente no usaría atributos de comportamiento en las clases como un enfoque predeterminado (es decir, póngalo en las definiciones de enlace en su lugar).

Todavía intentaría usar un proveedor (o una sobrecarga Bind<T>.To* con una lambda como una forma de escribir una fábrica con menos código), especialmente porque la capa de comportamiento de instancias se puede usar encima y tú " Obtendré todos tus objetos de la misma manera, lo cual es algo bueno.

La otra sugerencia que me gustaría hacer es que sus parámetros de demora y retardo calvo probablemente se puedan convertir en ciudadanos de primera clase de su árbol DI como, por ejemplo, un IConnectivityPolicy cosa que podría usarse en múltiples clases.

+0

Hola Rubén. Gracias por la respuesta. Pronto recibiré un fragmento de código para ti. Básicamente, lo que quise decir es que Ninject puede asegurarse de que solo hay 1 instancia de un objeto en particular para ti. De su documentación puede hacer esto utilizando el atributo [SingleInstance] o como señaló o utilizando la notación Bind, Bind () .To (). Usando . Pero si estoy creando las instancias yo mismo, ¿eso significa que debería asegurarme de que solo haya una?Estoy asumiendo que la respuesta es sí. Fragmento de código a seguir. – uriDium

+0

@Ruben. Tengo otra pregunta, en particular, qué hace el enlace .ToSelf() lograr. ¿Dónde sería esto útil? Puedo preguntar esto como una pregunta legítima si crees que podría ayudar a alguien más. Aún no veo nada en SO sobre esto. – uriDium

+1

Re ToSelf(), no es una mala pregunta en absoluto y vale la pena preguntar. Hay un AllowImplicitSelfBinding en Kernel. Cuando eso es falso, uno necesitaría usar ToSelf(). La razón por la que existe la vinculación implícita existe es que es algo común que queremos hacer, incluso si podría decirse que el uso de clases concretas es un antipatrón que no se debe alentar. Sin embargo, es discutible si es ideal exponerlo en el kernel de esta manera: creo que en StructureMap lo amplían en la noción de una política de escaneo que luego puede ser conectada para proporcionar una forma implícita de convención sobre la configuración. Unión. –

3

Ustedes han tenido una buena conversación yendo aquí, pero pensé en agregar una respuesta para ayudar a aclarar las cosas en base a la pregunta original.

La respuesta corta es que Ninject aún se asegurará de tener una sola instancia de un objeto si especifica .Using<SingletonBehavior> en su declaración vinculante, independientemente del mecanismo de activación, es decir, no omite los mecanismos de Ninject para garantizar solo un la instancia del objeto se crea al usar su propio proveedor usando la sintaxis .ToProvider - o la sintaxis .ToMethod para el caso.

Simplemente debe escribir su proveedor para suministrar instancias de objetos - no se requiere ninguna otra semántica en el proveedor. Por lo tanto, no se requiere todo el contenido básico requerido para crear instancias únicas como lo proporcionó en su muestra anterior.

Como ejemplo, su proveedor se vuelve mucho más simple; si bien, he añadido la solución de la ISomething y IOther usando el núcleo Ninject a su original ejemplo:

class MyClassProvider : SimpleProvider<MyClass> { 

    protected override MyClass CreateInstance(IContext context) { 
    int timeout = ConfigurationManager.AppSettings.Get("timeout"); 
    int delay = ConfiguraionManager.AppSettings.Get("delay "); 
    ISomething something = context.Kernel.Get<ISomething>(); 
    IOther other = context.Kernel.Get<IOther>(); 
    return new MyClass(something, other, timeout, delay); 
    } 
} 

Su declaración vinculante en su módulo de Ninject se vería así:

public class MyModule : StandardModule { 
    public override void Load() { 

    Bind<IMyClass>() 
     .ToProvider<MyClassProvider>() 
     .Using<SingletonBehavior>(); 
    } 
} 

Al utilizar el SingletonBehavior Ninject aún le dará solo una instancia de MyClass aunque esté usando su propio proveedor.

Esto es bastante fácil de probar. Puede agregar una propiedad DateTime a su clase, configurarlo en DateTime.Now en el constructor y examinar los objetos devueltos por varias llamadas a Get(): todos tendrán el mismo tiempo aunque haya creado la clase en su proveedor. Luego, cambie Using<SingletonBehavior> a Using<TransientBehavior> y observe la diferencia. Obtendrá uno nuevo cada vez, todo creado por su proveedor.

Espero que esta ayuda, por cierto, no estoy seguro si soy el Peter del que hablabas, pero si es así, me siento halagado.

+0

Hola, gracias por la respuesta. Pensé que podría usar el kernel para al menos comer el ISomething y el IOther, pero pensé que mi pregunta se estaba haciendo muy larga y lo hice como un ejercicio por mi cuenta. Ahora veo que Ninject probablemente envuelve a su proveedor y aún puede garantizar SingleInstance o Transient. Muy genial. – uriDium

+0

P.S. Sí, eras el Peter del que estaba hablando. :) Gracias P.P.S ¿Hay alguna otra documentación para Ninject. El sitio web (dojo) te da una buena idea básica pero no está completa. – uriDium

+0

¡Ningún problema! Para simplificarlo en exceso, cuando utiliza un proveedor o método para la creación de objetos, se conecta al canal de creación de objetos. Ninject básicamente mantiene una tabla hash de objetos, algo así como un caché, y busca allí primero para ver si el objeto está allí. Si es así y está usando 'SingletonBehavior', Ninject toma el que forma la tabla; de lo contrario, inicia el proceso de activación para el objeto que puede ser su propio mecanismo o su proveedor. Bastante genial. En cuanto a los documentos, utilicé el dojo y las publicaciones de blog con las que tropecé. Lea también muchos de los documentos sobre Autofac que ayudaron, también. –

Cuestiones relacionadas