7

Mi sto bagnando i piedi con DI/IoC e MEF in particolare.MEF e l'interfaccia separata portano a "Interfaccia per ogni classe"

Possiedo un'applicazione Web con due tipi di parti (forse più un giorno) definite da interfacce che richiedono l'accesso all'intero ambiente. L'applicazione ha una lista con implementazioni concrete per ogni tipo, composta da MEF.

L'ambiente è costituito da:

  • diversi repository
  • attuale richiesta di applicazione
  • motore di rendering
  • motore di navigazione
  • più alcune classi di utilità statici

Come posso metti la definizione di interfaccia s in un assemblaggio separato e allo stesso tempo specificare l'iniezione di ambiente?

Ovviamente, non posso semplicemente fare riferimento all'assembly principale perché è necessario fare riferimento all'assembly del contratto e non riesco a creare un riferimento circolare.

Sembra che sia necessario creare un'interfaccia per ciascuna classe dell'ambiente, i relativi tipi disponibili pubblicamente e così via ... Deve esserci un modo migliore ?!

Forse mi manca anche l'evidente difetto più grande qui, se qualcuno potesse indicarlo per me?

risposta

10

Se si desidera disaccoppiare le astrazioni dalle loro implementazioni (sempre un obiettivo degno), è necessario definire tali astrazioni nel proprio assieme.

Dal lato dell'implementazione, questo è facile da gestire, perché è necessario fare riferimento alle astrazioni per implementarle. Non c'è modo intorno a quello che si utilizzi MEF o no, di modo che è come è sempre stato:

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

Tuttavia, come dici tu, questo significa che non è possibile fare riferimento il vostro Composizione Radice dalla libreria di astrazione . Tuttavia, è come dovrebbe essere, perché le astrazioni non dovrebbero preoccuparsi di come vengono composte.

In altre parole, è necessario implementare la composizione delle dipendenze all'esterno della libreria di astrazione. Un buon candidato per questo è l'eseguibile stesso, mentre tu manterrai tutte le tue implementazioni concrete in una o due librerie separate.

La libreria di astrazione non avrà riferimenti, mentre sia i consumatori e gli esecutori avrebbero bisogno di fare riferimento a esso, quindi un grafico delle dipendenze potrebbe assomigliare a questo:

Composition Root --> Abstractions <-- Implementations 

Dove le frecce indicano un riferimento.

+0

"Impossibile fare riferimento alla composizione radice dalla libreria di astrazione" - Questo è l'obiettivo, ma anche la fonte della mia confusione. Se le mie astrazioni hanno una proprietà di tipo "Engine", che è definita e implementata nella mia libreria di implementazione, devo creare un'interfaccia "IEngine" anche per questo tipo nella libreria di astrazione? Ora, se devo fare riferimento a più tipi, ognuno di nuovo con le proprie dipendenze, avrei bisogno di astrarre tutti quelli nella libreria di astrazione, non è vero? – wagi

+2

Sì, è corretto. Tutte queste interfacce aggiuntive possono sembrare un po 'eccessive, ma ognuna è in realtà una ** Seam ** in cui si disaccoppia l'implementatore dal consumatore. Il risultato finale è un sistema più flessibile. Il vantaggio potrebbe non essere immediatamente ovvio, ma una volta che inizi a sperimentare il potere di consumare ed esporre astrazioni invece di tipi concreti, non vorrai più tornare :) –

+0

grazie, quindi quello che pensavo fosse troppo, in realtà è perfettamente a posto e necessario! – wagi