2010-03-01 14 views
7

Me estoy mojando los pies con DI/IoC y MEF en particular.MEF y el conjunto de interfaz por separado conduce a "Interfaz para cada clase"

Tengo una aplicación web que tiene dos tipos de partes (quizás más algún día) definidas por interfaces que necesitan acceso a todo el entorno. La aplicación tiene una lista con implementaciones concretas para cada tipo, compuesta por MEF.

El entorno se compone de:

  • varios repositorios
  • solicitud actual aplicación
  • motor de render
  • motor de navegación
  • además de algunas clases de utilidad estáticas

¿Cómo puedo poner la definición de interfaz s en un conjunto separado y, al mismo tiempo, especifique la inyección del entorno?

Obviamente, no puedo simplemente hacer referencia al ensamblaje principal porque necesita hacer referencia al ensamblaje del contrato y no puedo crear una referencia circular.

Parece que necesito crear una interfaz para cada una de las clases de entorno, y sus tipos disponibles públicamente y así sucesivamente ... ¿Tiene que haber una manera mejor?

Tal vez también me estoy perdiendo la falla obvia más grande aquí, si alguien podría señalarlo por mí?

Respuesta

10

Si desea desacoplar sus abstracciones de sus implementaciones (siempre un objetivo digno), debe definir esas abstracciones en su propio conjunto.

Desde el punto de vista de la implementación, esto es fácil de tratar, ya que necesita hacer referencia a las abstracciones para implementarlas. No hay forma de evitar que si se utiliza el MEF o no, así que eso es lo que siempre ha sido:

[Import(typeof(IFoo))] 
public class MyFoo : IFoo { } 

Sin embargo, como usted dice, esto significa que no se puede hacer referencia a su Composición Raíz de la biblioteca de abstracción . Sin embargo, así es como debería ser, porque las abstracciones no deberían preocuparse por cómo se componen.

En otras palabras, debe implementar la composición de las dependencias fuera de la biblioteca de abstracción. Un buen candidato para eso es el ejecutable en sí, mientras que usted mantendría todas sus implementaciones concretas en una o bibliotecas separadas.

La biblioteca de abstracción no tendrá referencias, mientras que tanto los consumidores como los ejecutores tendrían que hacer referencia a ella, por lo que un gráfico de la dependencia podría tener este aspecto:

Composition Root --> Abstractions <-- Implementations 

donde las flechas indican una referencia.

+0

"no se puede hacer referencia a su raíz de composición de la biblioteca de abstracción": ese es el objetivo, pero también el origen de mi confusión. Si mis abstracciones tienen una propiedad del tipo "Motor", que está definida e implementada en mi biblioteca de implementación, ¿necesito crear también una interfaz "IEngine" para este tipo en la biblioteca de abstracción? Ahora, si tengo varios tipos que necesitan referencia, cada uno con sus propias dependencias, tendré que abstraerlos todos en la biblioteca de abstracción, ¿o no? – wagi

+2

Sí, eso es correcto. Todas esas interfaces adicionales pueden parecer mucho sobrecargadas, pero cada una es en realidad una ** Seam ** en la que desacopla al implementador del consumidor. El resultado final es un sistema acoplado más flexible. El beneficio puede no ser inmediatamente obvio, pero una vez que comienzas a experimentar el poder de consumir y exponer abstracciones en lugar de tipos concretos, nunca querrás volver :) –

+0

gracias, entonces lo que pensé que era demasiado, en realidad está perfectamente bien ¡y necesitado! – wagi

Cuestiones relacionadas