¿Cómo podría integrarse la inyección de dependencia al lenguaje? [cerrado]

10

He estado pensando un poco en cómo la inyección de dependencia podría integrarse mejor directamente en un lenguaje similar a C #. Se me ocurrió una posible solución sobre la que me gustaría conocer su opinión. No he usado muchos marcos de inyección de dependencia, por lo que podría haber algo que estoy pasando por alto

De todos modos, la idea es poder declarar propiedades como "inyectables" usando una palabra clave. Cuando se crea una instancia de un objeto y esa propiedad no se inicializa a través del constructor o el inicializador de objeto, solicita una instancia de ese tipo de propiedad de algún servicio global.

De manera similar, registra controladores para diferentes tipos en ese servicio para que pueda instanciar el tipo de propiedad inyectado.

La ventaja de usar este tipo de arquitectura IMO es que es bastante flexible y fácil de usar. La desventaja es que puede haber algo de sobrecarga de hacer la llamada al singleton cada vez que inicia una clase que tiene inyección.

Por otra parte, eso solo es un problema para las clases que se instancian con frecuencia en una solución de alto rendimiento, por lo que no debería ser un gran problema. Tal vez podría usar algún tipo de fábrica en esos casos.

Pensamiento, problemas, preguntas, mejores ideas?

Código

public class SomeClass
{

  public SomeClass()
  {
     //implicit behavior if Animal is not set in constructor or initializer
    this.Animal =  GlobalInjector.Get(this,typeof(Mammal))

  }

  public injectable Mammal Animal  
  {
   get;
   set;
  }
}


 GlobalInjector.Register(typeof(Mammal), () => return new Mammal(someParameter));
Homde
fuente
¿Podría dar un ejemplo de pseudocódigo para aquellos de nosotros que no estamos familiarizados con DI? PD. ¿Quizás también pueda responder mi pregunta sobre DI? :)
Steven
2
No estoy seguro de entenderlo. Puede obtener todo eso con un contenedor DI global y un atributo '[inyectable]' en lugar de una palabra clave, ¿verdad?
Nikkie
Hola, intenté escribir un poco sobre DI en su pregunta, aunque no estoy seguro de que responda
Homde
nikie: Sí claro, supongo que podrías implementar el mecanismo real de diferentes maneras, estoy más interesado si la lógica subyacente es sólida
Homde
Entonces, ¿qué es diferente entre este y el IoC existente además de su palabra clave adicional?
Matthew Whited

Respuestas:

7

Hay cosas que pertenecen a los idiomas y cosas que no. Hace mucho tiempo, C reconoció que IO no pertenecía al lenguaje porque es externo al modelo informático y puede implementarse con bibliotecas de funciones.

La inyección de dependencia es así. Es externo al lenguaje y se puede implementar con los marcos apropiados.

Uno de los problemas con los idiomas modernos es que intentan hacer demasiado. Finalmente, esos idiomas colapsan bajo su propio peso a medida que los programadores huyen a idiomas más simples.

Tío Bob.
fuente
Estoy de acuerdo en teoría, no se puede tener un lenguaje en el que cada función sea una característica del lenguaje sin que se hinche. Sin embargo, siempre hay espacio para nuevas abstracciones más altas que nos ayudan a escribir un mejor código. Quizás la inyección de dependencia en sí no es el problema que necesita solución, sino el problema que aborda, es decir, una forma de facilitar la reducción de dependencias. Sin embargo, esta podría no ser la mejor manera de hacerlo :)
Homde
5

No es necesario

Una de las cosas que más me gustan de los mejores marcos de DI que he usado es que el código de configuración de nivel superior es la única parte de su código que necesita saber sobre DI. El cableado automático se realiza a nivel de contenedor y configuración / "carga de módulos", y su código de aplicación puede ser completamente ajeno a él.

Esto significa que no hay atributos, sin cadenas mágicas, sin convenciones. Cada fragmento de código solo sabe que acepta código en su constructor (/ propiedades / métodos), y eso es todo.

Con un diseño como ese, no es necesario alterar el idioma para admitir la inyección de dependencia.

Es potencialmente peligroso

Lo que más temo de un sistema de inyección de dependencia integrado en el lenguaje es que levantaría una barrera contra cualquier otra implementación, pero probablemente se pintaría en un rincón en algún aspecto.

Algunas formas en las que podría pintarse en una esquina:

  • Solo admite la configuración basada en XML o solo la configuración basada en código
  • No poder admitir limpiamente el patrón de diseño de fábrica (no solo componentes transitorios: componentes generados en tiempo de ejecución)
  • De alguna manera, cambié mi código, así que me vi obligado a usar la inyección de dependencia, y no pude simplemente instanciar mi clase para pruebas unitarias
  • No es compatible con ciclos de vida personalizados
  • No ser extensible
  • No ser reemplazable en los casos en que necesito una mayor personalización
  • Estar roto de alguna manera que aún no entendemos, porque nosotros, los usuarios de .Net, no hemos estado usando DI lo suficiente como para saber las trampas
Merlyn Morgan-Graham
fuente
4

¿Has visto el Marco de Extensibilidad Administrada que viene con .NET 4? Aquí hay un artículo que escribí con algunos ejemplos. Básicamente es una forma de inyección de dependencia integrada en .NET, con las características adicionales de capacidad de detección en tiempo de ejecución.

Las inyecciones de propiedades se ven así:

class Program
{
    [Import]
    public IMessageSender MessageSender { get; set; }
}

Las inyecciones de constructor se ven así:

class Program
{
    [ImportingConstructor]
    public Program(IMessageSender messageSender) 
    {
    ...
    }
}

Puede importar campos, importar opcionalmente, importar colecciones de servicios, incluida la importación diferida con metadatos para que pueda buscar un servicio apropiado para crear instancias. Incluso puede volver a importar en tiempo de ejecución para buscar nuevas extensiones.

Scott Whitlock
fuente
Si bien MEF es realmente genial para cosas de complementos, no creo que me gustaría usarlo como mecanismo general de DI
Homde
1
@MKO - ¿Puedes dar más detalles sobre lo que falta? Soy consciente de todos los artículos en los que Glenn Block compite para tranquilizar a la gente de que MEF no está dispuesto a reemplazar todos los marcos de DI, pero si nos fijamos en los detalles, es obvio que es más una declaración política que otra cosa. Sin embargo, si puede dar una buena lista de características que MEF carece en comparación con otros marcos DI, eso ayudará a las personas a tomar una decisión informada. Además, la pregunta es acerca de los marcos DI en C #, y MEF es claramente un contenedor DI en el marco .NET.
Scott Whitlock
2
  1. Realmente no se describe el mecanismo de configuración, que en mi humilde opinión es el bit complicado. ¿Cómo hace que todo el código que se ejecuta en un hilo use la conexión DB A y todo el código en el otro hilo B? ¿Cómo bloquea la inyección de un determinado recurso, porque el usuario actualmente conectado no tiene permiso para acceder?
  2. No use un inyector global. No use nada global, o bien podría usar variables globales. No, usar OOP-speak como singleton o "static" en lugar de global no cambia su naturaleza global.
  3. Considere un contenedor de ámbito dinámico. Si bien el alcance léxico ha ganado legítimamente contra el alcance dinámico, creo que el alcance dinámico sería un excelente reemplazo para el alcance global. La herencia diferencial sería una buena implementación (como en la herencia basada en prototipos).
  4. Creo que un mecanismo DI ordenado por el lenguaje debería ser realmente simple, nada de esas cosas empresariales que son la norma en C # y Java. Un mecanismo de alcance dinámico con una capa de configuración simple en la parte superior podría hacer el truco. Las soluciones empresariales podrían ser organizadas por terceros.
Waquo
fuente