IOC tra presentazione e livello infrastruttura

0

Domanda :
Vorrei impostare il mapping delle dipendenze da un file * .config da un progetto che non ha riferimenti al progetto che contiene la classe concreta.

Scenario :
Userò termini da C #, Microsoft Unity e Visual Studio: ho un livello di presentazione con un progetto di servizio web e un progetto winform, un livello infrastruttura che comunica con gli archivi e c'è un livello logico di core business che definisce interfacce che l'infrastruttura deve implementare.

Progetti :
Presentazione :
DIApplication.WebServices - fa riferimento ai progetti Core + DependencyResolution
DIApplication.Winform - fa riferimento ai progetti Core + DependencyResolution

Infrastrutture :
DIApplication.Data - Comunica con repository, fa riferimento al Core
DIApplication.DependencyResolution - Registra le dipendenze dai progetti Core a Data. Questi sono gli unici due progetti a cui fa riferimento

Nucleo :
DIApplication.Core - Definisce le interfacce, non fa riferimento a nulla

Esempio :
Per un esempio, dirò che ho l'interfaccia DIApplication.Core.IRepository e la classe DIApplication.Data.RepositoryA e la classe DIApplication.Data.RepositoryB.

Va bene dire che il progetto DependencyResolution registrerà le dipendenze:

//If Application == WebService
container.RegisterType<IRepository , RepositoryA >();
//Else
container.RegisterType<IRepository , RepositoryB >();

Ma quello che mi piacerebbe fare è che Webservices Web.config mappa IRepository to RepositoryA, mentre l'app Winforms.config IRepository to RepositoryB

Webservices:     

< register type="DIApplication.Core.IRepository, DIApplication.Core" mapTo=" DIApplication.Data.RepositoryA, DIApplication.Data" />

WinForms:

< register type="DIApplication.Core.IRepository, DIApplication.Core" mapTo=" DIApplication.Data.RepositoryB, DIApplication.Data" />

Il problema (credo) è che né DIapplication.Webservices o Winforms conoscono DIapplication.Data, quindi si interrompe sulla parte finale di questa chiamata in DIApplication.DependencyResolution:

IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container);

Con l'errore:

The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047) 

C'è un modo per aggirare questo problema senza dover includere un riferimento a DIApplication.Data all'interno di DIApplication.Webservices e Winforms?

Forse lo sto guardando nel modo sbagliato. So che rompe la nozione di separazione delle preoccupazioni, in cui il livello di presentazione non dovrebbe sapere né preoccuparsi di come i dati vengano conservati nei repository, solo che lo è. Ma voglio anche guidare le dipendenze sulla base del progetto in esecuzione.

    
posta Dszordan 29.10.2014 - 21:43
fonte

1 risposta

2

Il contesto della tua applicazione decide tutto.

Per illustrare il motivo per cui questo è vero, iniziamo prima con lo scopo di inversione del controllo o IOC. Le finalità di IOC sono estensibilità e ridimensionamento orizzontale.

Nell'estensibilità, l'applicazione deve decidere quale implementazione utilizzare in un particolare insieme di circostanze. Ad esempio, se l'utente sceglie di pagare tramite PayPal, deve scegliere l'implementazione PayPalPaymentProvider anziché l'implementazione Authorize.NET.

Per il ridimensionamento orizzontale, l'implementazione è disaccoppiata dal codice dell'applicazione in modo da poter facilmente scalare scrivendo nuove implementazioni e impostandole nel contesto dell'applicazione. Ad esempio, se la mia applicazione utilizza attualmente MySql, ma ora sono al punto in cui MySql non sta funzionando bene perché la mia applicazione è diventata troppo popolare, usando IOC posso semplicemente scrivere una nuova implementazione di database specifica per SQL e buttarla fuori il codice MySql senza dover modificare alcuna logica applicativa.

Tutto ciò detto, aggiungiamo il fatto che il livello di presentazione è quasi sempre legato a un ambiente specifico su cui deve essere eseguito. A meno che tu non scriva il tuo host o sistema operativo o tu astragga la tua intera interfaccia utente nel proprio progetto che è poi ospitato da un progetto di contesto, il progetto che contiene la tua interfaccia utente sarà il decisore per tutto ciò che riguarda l'implementazione.

Ora, per rispondere alla tua domanda. Non è necessario avere un riferimento al progetto DIApplication.Data nei propri progetti DIApplication.Webservices o DIApplication.Winforms e non si desidera fare riferimento direttamente perché in tal modo si elimina lo scopo dell'utilizzo dello IOC. Tuttavia, sarà necessario copiare la DLL per DIApplication.Data nel contesto delle applicazioni in modo che possa leggere l'assembly. La definizione di quale implementazione si desidera utilizzare per l'IOC in web.config e app.config è una buona pratica.

Tuttavia, affinché il CIO sia in grado di leggere e creare un'istanza per l'implementazione concreta, deve essere in grado di trovarlo. L'idea qui è che è possibile scambiare quella dll con una diversa implementazione concreta, cambiare il file di configurazione in modo che punti alla nuova istanza concreta e tutto continuerà a funzionare senza dover ricostruire l'applicazione, tanto meno dover modificare qualsiasi codice .

Quindi, per riassumere la risposta, tutto ciò che dovresti davvero fare a questo punto è usare un'azione post-build per copiare l'implementazione concreta nelle cartelle bin per i tuoi Windows Form e le tue applicazioni Web.

    
risposta data 29.10.2014 - 23:00
fonte