unity - tipos de inyeccion de dependencias c#




¿Cómo evitar la dependencia del constructor de inyección de dependencia? (6)

Encuentro que mis constructores están empezando a verse así:

public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )

con cada vez mayor lista de parámetros. Ya que "Container" es mi contenedor de inyección de dependencia, ¿por qué no puedo hacer esto?

public MyClass(Container con)

para cada clase? ¿Cuáles son las desventajas? Si hago esto, siento que estoy usando una estática glorificada. Por favor comparta sus pensamientos sobre la locura de inyección de dependencia y la IoC.


¿Qué marco de inyección de dependencia está utilizando? ¿Ha intentado utilizar la inyección basada en incubadora en su lugar?

El beneficio de la inyección basada en el constructor es que parece natural para los programadores de Java que no usan frameworks DI. Necesita 5 cosas para inicializar una clase, entonces tiene 5 argumentos para su constructor. El inconveniente es lo que ha notado, se vuelve difícil de manejar cuando tiene muchas dependencias.

Con Spring, podría pasar los valores requeridos con los configuradores en su lugar y podría usar las anotaciones necesarias para imponer que se inyecten. El inconveniente es que necesita mover el código de inicialización del constructor a otro método y hacer que Spring llame después de inyectar todas las dependencias al marcarlo con @PostConstruct. No estoy seguro de otros marcos, pero supongo que hacen algo similar.

Ambas formas funcionan, es una cuestión de preferencia.


Este es el enfoque que utilizo

public class Hero
{

    [Inject]
    private IInventory Inventory { get; set; }

    [Inject]
    private IArmour Armour { get; set; }

    [Inject]
    protected IWeapon Weapon { get; set; }

    [Inject]
    private IAction Jump { get; set; }

    [Inject]
    private IInstanceProvider InstanceProvider { get; set; }


}

Aquí hay un enfoque básico sobre cómo realizar las inyecciones y ejecutar el constructor después de inyectar los valores. Este es un programa totalmente funcional.

public class InjectAttribute : Attribute
{

}


public class TestClass
{
    [Inject]
    private SomeDependency sd { get; set; }

    public TestClass()
    {
        Console.WriteLine("ctor");
        Console.WriteLine(sd);
    }
}

public class SomeDependency
{

}


class Program
{
    static void Main(string[] args)
    {
        object tc = FormatterServices.GetUninitializedObject(typeof(TestClass));

        // Get all properties with inject tag
        List<PropertyInfo> pi = typeof(TestClass)
            .GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
            .Where(info => info.GetCustomAttributes(typeof(InjectAttribute), false).Length > 0).ToList();

        // We now happen to know there's only one dependency so we take a shortcut just for the sake of this example and just set value to it without inspecting it
        pi[0].SetValue(tc, new SomeDependency(), null);


        // Find the right constructor and Invoke it. 
        ConstructorInfo ci = typeof(TestClass).GetConstructors()[0];
        ci.Invoke(tc, null);

    }
}

Actualmente estoy trabajando en un proyecto de hobby que funciona así https://github.com/Jokine/ToolProject/tree/Core


La dificultad de pasar en los parámetros no es el problema. El problema es que tu clase está haciendo demasiado, y debería dividirse más.

La inyección de dependencia puede actuar como una advertencia temprana para las clases que se hacen demasiado grandes, especialmente debido al dolor creciente de pasar en todas las dependencias.


Leí todo este hilo dos veces y creo que las personas responden por lo que saben, no por lo que se les pregunta.

La pregunta original de JP parece que está construyendo objetos mediante el envío de un programa de resolución, y luego un montón de clases, pero suponemos que esas clases / objetos son en sí mismos servicios, listos para ser inyectados. ¿Y si no lo son?

JP, si está buscando aprovechar el DI y desear la gloria de mezclar la inyección con datos contextuales, ninguno de estos patrones (o supuestos "anti-patrones") aborda eso específicamente. En realidad se reduce a usar un paquete que lo apoyará en tal esfuerzo.

Container.GetSevice<MyClass>(someObject1, someObject2)

... este formato rara vez es compatible. Creo que la dificultad de programar dicho soporte, sumado al rendimiento miserable que se asociaría con la implementación, lo hace poco atractivo para los desarrolladores de código abierto.

Pero debería hacerse, porque debería poder crear y registrar una fábrica para MyClass'es, y esa fábrica debería poder recibir datos / entradas que no se convierten en un "servicio" solo por el simple hecho de pasar. datos. Si "antipatrón" tiene que ver con consecuencias negativas, entonces forzar la existencia de tipos de servicios artificiales para pasar datos / modelos es ciertamente negativo (a la par con su sentimiento de envolver sus clases en un contenedor. Se aplica el mismo instinto).

Sin embargo, hay un marco que puede ayudar, incluso si se ven un poco feos. Por ejemplo, Ninject:

Creando una instancia usando Ninject con parámetros adicionales en el constructor

Eso es para .NET, es popular y todavía no está tan limpio como debería, pero estoy seguro de que hay algo en cualquier idioma que elijas emplear.


No creo que los constructores de su clase deban tener una referencia al período de contenedor de IOC. Esto representa una dependencia innecesaria entre su clase y el contenedor (¡el tipo de dependencia que el IOC está tratando de evitar!).


Tiene razón en que si utiliza el contenedor como Localizador de servicios, es más o menos una fábrica estática glorificada. Por muchas razones considero que esto es un anti-patrón .

Uno de los maravillosos beneficios de Constructor Injection es que hace que las violaciones del Principio de Responsabilidad Única sean evidentes.

Cuando eso sucede, es hora de refactorizar los servicios de fachada . En resumen, cree una nueva interfaz de grano más grueso que oculte la interacción entre algunas o todas las dependencias de grano fino que necesita actualmente.







ioc-container