unity net mvc injection dependency asp .net inversion-of-control ioc-container

.net - net - IoC.Resolve vs Constructor Injection



web api 2 unity dependency injection (8)

no es necesario crear clases que tengan 5 parámetros en el constructor, y siempre que vayas a crear una instancia de esa clase no necesitarás proporcionar nada

Un par de puntos:

  • Si está utilizando un contenedor DI, debería crear las instancias de esa clase para usted. En ese caso, no tiene que proporcionarle nada para uso de producción. Para la prueba, tendrá que proporcionarle las dependencias a través del constructor, pero:
  • Si la clase depende de (usa de alguna manera) esas 5 cosas de las que estás hablando proporcionando al constructor (y no las estarías proporcionando si no fuera así), tendrás que proporcionarlas de una manera o de la otra. otro. Al realizar la prueba (que es el único momento en que debería tener que llamar al constructor), puede pasarle esas cosas a través del constructor o puede escribir el código para configurar el contenedor y agregar esas 5 cosas para que cuando IoC.Resolve() llama a IoC.Resolve() , en realidad están allí. Pasarles al constructor es mucho más fácil, diría yo.

Las dependencias existirán incluso si no lo haces aparente a través de la API de la clase (es el constructor en este caso). Sin embargo, será mucho más difícil de entender y probar las clases que intentan ocultar sus dependencias de esta manera.

Escuché a muchas personas decir que es una mala práctica usar IoC.Resolve (), pero nunca escuché una buena razón por la cual (si todo se trata de pruebas, puedes burlarte del contenedor y listo).

ahora las ventajas de usar Resolve en lugar de Constructor Injection es que no necesita crear clases que tengan 5 parámetros en el constructor, y siempre que vaya a crear una instancia de esa clase no necesitará proporcionarla. cualquier cosa


Debo señalar que no es necesariamente malo omitir la inyección del constructor y usar inyección estática. Hay grandes aplicaciones de esto, el ejemplo más concreto es su uso en una implementación de patrón de fábrica.

public static class ValidationFactory { public static Result Validate<T>(T obj) { try { var validator = ObjectFactory.GetInstance<IValidator<T>>(); return validator.Validate(obj); } catch (Exception ex) { var result = ex.ToResult(); ... return result; } } }

Lo uso con StructureMap para manejar mi capa de validación.

Editar: Otro ejemplo que tengo de usar el contenedor directamente es hacer que algunos de tus objetos de dominio sean únicos sin convertirlos en clases estáticas e introducir toda la rareza que tienen las clases estáticas.

En algunos de mis puntos de vista, conecto algunas entidades como esta. Normalmente nos gustaría un Enum con un atributo de Descripción para darme 3 opciones de valor, pero el tercero en este caso también debe ser una cadena y no una int, así que creé una interfaz con esas 3 propiedades y heredo todos los objetos de dominio de eso. Luego hago que mi contenedor escanee mi ensamblaje y los registre automáticamente para luego sacarlos. Solo tengo

SomeObject ISomeView.GetMyObject { get { return new SomeObject { EmpoweredEnumType = ObjectFactory.GetNamedInstance<IEmpEnum>("TheObjectName"); } }


Ioc.Resolve es esencialmente el patrón Localizador de servicios. Tiene su lugar, pero no es ideal. La inyección de constructores es preferida desde el punto de vista de la arquitectura, ya que las dependencias son más explícitas, mientras que la SL oculta las dependencias dentro de una clase. Esto reduce la capacidad de prueba y hace que el proceso sea más complejo de lo necesario.

Si puedo, le sugiero que lea mi serie reciente sobre técnicas para reducir el acoplamiento de códigos, que cubre SL, DI e IoC.


Si crea clases que tienen 5 dependencias, tiene problemas distintos de IoC.Resolve.

La extracción de dependencias (en lugar de tener que empujarlas a través de un constructor) pasa completamente por alto el punto de utilizar el marco de trabajo de IoC. Quieres invertir las dependencias. Sus clases no dependen del marco de trabajo de IoC, sino al revés.

Si no necesita todas las dependencias en ciertos escenarios, entonces quizás deba dividir su clase, o tener algunas dependencias hechas opcionales haciéndolas dependencias de propiedad.

Tus clases dependen del contenedor. No funcionarán a menos que les proporciones uno. Si es uno real o uno falso no importa. Están vinculados inherentemente al contenedor a través de la dependencia estática. Esto le impone trabajo adicional para hacer cualquier cosa con sus clases. Cada vez que quiera usar su clase, debe arrastrar el contenedor con ellos. Sin ningún beneficio! El localizador de servicios es solo una bolsa global de todo, lo cual está en contra de todos los principios de la programación orientada a objetos.


Una ventaja es que con la inyección de constructor, todas las dependencias de clase son visibles desde el principio.

Con .Resolve tienes que leer el código solo para descubrir las dependencias.


Yo diría que es una gran cantidad de parámetros para ser inyectados.

Esfuércese por un parámetro, tal vez 2 como máximo, que es en casi todos los escenarios posibles, y por supuesto debe ser una interfaz. Más que eso, y huelo una rata (falla de diseño).


IoC.Resolve<> es un ejemplo del patrón de Localizador de servicios . Ese patrón impone algunas restricciones que la inyección del constructor no:

  • Los objetos no pueden tener un contexto más detallado que el dominio de la aplicación, debido a las llamadas estáticas
  • Los objetos deciden qué versiones de dependencias resolver. Todas las instancias de una determinada clase obtendrán la misma configuración de dependencia.
  • La tentación de vincular el código al contenedor es alta, por ejemplo, en lugar de crear una fábrica que revele la intención.
  • Las pruebas unitarias requieren la configuración del contenedor, donde las clases podrían simplemente crearse y usarse de otra manera. (Esto es especialmente problemático cuando quiere probar varias configuraciones de la misma clase, debido al segundo problema anterior).
  • La estructura de una aplicación no se puede deducir de su API pública. (Los parámetros del constructor son algo bueno . No son un problema que deba sentir la necesidad de resolver).

Estas limitaciones, en mi opinión, relegan el patrón de Localizador de servicios a un término medio entre la inyección de gran bola de barro y la inyección de dependencia: útil si debe usarlo, pero de lejos no es la mejor opción.


Como la pregunta es discutible, no voy a decir "usa esto o aquello"

Parece que usar el Localizador de servicios no es malo si está bien para depender de él (y usualmente lo hacemos de cualquier forma en un marco DI). Con DI podemos cambiar fácilmente el marco, con Service Locator creamos acoplamiento a SL como parte del framework.

Con respecto a la respuesta de Bryan Watts cuando lees más adelante en Service Locator vs Dependency Injection

... Con la inyección [constructor] no hay una solicitud explícita, el servicio aparece en la clase de aplicación, de ahí la inversión del control .

La inversión del control es una característica común de los marcos, pero es algo que tiene un precio. Tiende a ser difícil de entender y genera problemas cuando intenta depurar. Entonces, en general, prefiero evitarlo a menos que lo necesite. Esto no quiere decir que sea algo malo, solo que creo que necesita justificarse sobre la alternativa más directa.

Y luego, si lo lee más adelante, es otra justificación para usar realmente la inyección de constructor (Inversión de control).

Mi opinión es que en proyectos pequeños está bien usar SL, ya que lo principal no es crear un acoplamiento entre nuestras clases personalizadas.

El uso de StructureMap exmaple debería ser aceptable:

public class Demo { private ISomething something = ObjectFactory.GetInstance<ISomething>(); private IFoo foo = ObjectFactory.GetInstance<IFoo>(); }

Sí, el código depende de SM Frx, pero ¿con qué frecuencia cambia el DI Frx de todos modos?

Y para la prueba unitaria se puede configurar un simulacro

public class SomeTestClass { public SomeTest() { ObjectFactory.Inject<ISomething>(SomeMockGoesHere); ObjectFactory.Inject<IFoo>(SomeMockGoesHere); Demo demo = new Demo() //will use mocks now } }

Las ventajas de usar Resolve en lugar de Constructor Injection es que no necesita crear clases que tengan 5 parámetros en el constructor.

pero puede terminar haciendo más "plomería" para las pruebas unitarias.