Pregunta

Algo que me ha estado molestando desde que leí una respuesta en otra pregunta StackOverflow (los ahora me elude uno precisos), donde un usuario se indique algo así como " Si llama al Servicio de localización, lo estás haciendo equivocado. "

Era alguien con una alta reputación (en los cientos de miles, creo) por lo que tienden a creer que esta persona podría saber lo que están hablando. He estado usando DI para mis proyectos desde que empecé a aprender sobre él y lo bien que se relaciona con la Unidad de Pruebas y lo que no. Es algo que estoy bastante cómodo con el ahora y yo piensan Yo sé lo que estoy haciendo.

Sin embargo, hay una gran cantidad de lugares en los que he estado usando el Servicio de localización de dependencias se resuelven en mi proyecto. Una vez buen ejemplo viene de mis implementaciones ModelBinder.

ejemplo de un aglutinante modelo típico.

public class FileModelBinder : IModelBinder {
    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext) {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue("id");

        IDataContext db = Services.Current.GetService<IDataContext>();
        return db.Files.SingleOrDefault(i => i.Id == id.AttemptedValue);
    }
}

no es una verdadera aplicación - sólo un ejemplo rápido

Desde la implementación ModelBinder requiere una nueva instancia cuando una carpeta es primero solicitado, es imposible utilizar la inyección de dependencias en el constructor para esta aplicación en particular.

Es de esta manera en muchas de mis clases. Otro ejemplo es el de un proceso de caducidad de la caché que se ejecuta un método cada vez que un objeto de caché expira en mi página web. Tengo un montón de llamadas de base de datos y lo que no. Allí también estoy usando un localizador de servicio para obtener la dependencia requerida.

Otro problema que tuve recientemente (que he publicado una pregunta aquí sobre) era que todos mis controladores requieren una instancia de IDataContext que utilicé DI para - pero un método de acción requiere una instancia diferente de IDataContext. Por suerte Ninject vino al rescate con una dependencia llamada. Sin embargo, esto se sentía como una chapuza y no una solución real.

pensé que, al menos, entiende el concepto de separación de las preocupaciones razonablemente bien, pero parece que hay algo fundamentalmente equivocado con la forma en que entiendo la inyección de dependencia y el patrón Service Locator - y yo no sé lo que es <. / p>

La forma en que actualmente lo entiendo - y esto podría estar equivocado, así - es que, al menos en MVC, las miradas ControllerFactory para un constructor para un controlador y pide el propio Servicio de localización para obtener las dependencias necesarias y luego los pasa . sin embargo, puedo entender que no todas las clases y lo que no tiene una fábrica para crearlos. Así que me parece que algún patrón Service Locator es aceptable ... pero ...

  1. Cuando es no aceptable?
  2. ¿Qué tipo de patrón que debe estar en la mirada hacia fuera para cuando debería replantearse la forma en que estoy usando el patrón Service Locator?
  3. ¿Es mi ModelBinder aplicación equivocada? Si es así, ¿qué es lo que tengo que aprender a solucionarlo?
  4. En otra pregunta en la línea de éste usuario Marcos Seemann recomienda una fábrica abstracta - ¿Cómo se relaciona esto ?

Creo que eso es todo -. Realmente no puedo pensar en ninguna otra cuestión para ayudar a mi comprensión, pero ninguna información adicional es muy apreciada

DI entiendo que podría no ser la respuesta para todo y yo podría ir al agua en cómo ponerlo en práctica, sin embargo, parece que funciona de la manera que esperaba que con la Unidad de Pruebas y lo que no.

No estoy en busca de código para arreglar mi implementación de ejemplo -. Estoy mirando para aprender, buscando una explicación para arreglar mi comprensión defectuosa

Me gustaría stackoverflow.com tenía la posibilidad de guardar proyectos de preguntas. También espero que el que responde a esta pregunta recibe la cantidad adecuada de reputación para responder a esta pregunta, ya que creo que estoy pidiendo mucho. Gracias, por adelantado.

¿Fue útil?

Solución

Tenga en cuenta lo siguiente:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass(IMyInterface myInterface, IMyOtherInterface myOtherInterface)
  {
    // Foo

    _myInterface = myInterface;
    _myOtherInterface = myOtherInterface;
  }
}

Con este diseño soy capaz de expresar los requisitos de dependencia para mi tipo. El tipo en sí no es responsable de saber cómo instanciar cualquiera de las dependencias, se les da a él (inyectada) por lo que la resolución de mecanismo se utiliza [típicamente un contenedor IoC]. Considerando lo siguiente:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass()
  {
    // Bar

    _myInterface = ServiceLocator.Resolve<IMyInterface>();
    _myOtherInterface = ServiceLocator.Resolve<IMyOtherInterface>();
  }
}

Nuestra clase es ahora depende de la creación de las instancias specfic, sino a través de delegación a un localizador de servicio. En este sentido, el servicio de ubicación se puede considerar un anti-patrón porque no se está exponiendo dependencias, pero que está permitiendo problemas que se pueden capturar mediante la recopilación de burbuja para arriba en tiempo de ejecución. (Una buena lectura es aquí ). Usted ocultando complejidades.

La elección entre uno u otro depende realmente de lo que su edificio en la parte superior y los servicios que presta. Normalmente, si usted está construyendo una aplicación desde cero, elegiría DI todo el tiempo. Mejora la capacidad de mantenimiento, promueve la modularidad y hace que se prueben tipos mucho más fácil. Pero, teniendo ASP.NET MVC3 como ejemplo, fácilmente se podría aplicar SL como su horneado en el diseño.

Siempre se puede ir para un diseño compuesto donde se podía utilizar IOC / DI con SL, al igual que el uso de la Común Servicios de localización . Usted partes componentes podría ser cableados a través de DI, pero expuesto a través SL. Incluso se puede tirar composición en la mezcla y el uso algo así como el Marco Extensibilidad Administrada (que a su vez apoya DI, pero también puede ser conectado a otros contenedores IoC o localizadores de servicio). Es una elección gran diseño para que, en general, mi recomendación sería para IOC / DI siempre que sea posible.

Su diseño específico no diría que está mal. En este caso, el código no es responsable de crear una instancia del modelo propio aglutinante, que pasa al marco para que tenga ningún control sobre eso y su uso del servicio de localización probablemente podría cambiar fácilmente acceder a un contenedor IoC. Pero la acción de llamar a la resolución sobre el contenedor IoC ... ¿Quieres que no considera que la ubicación del servicio?

Con una Abstract Factory la fábrica está especializada en la creación de tipos específicos. No se registra tipos de resolución, se registra esencialmente una fábrica abstracta y que se construye cualquier tipo que solicite. Con un Servicio de localización que está diseñado para localizar servicios y devolver esos casos. Similares desde el punto de vista de convenciones, pero muy diferente en el comportamiento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top