La mia azienda ha molti servizi WCF che potrebbero o non potrebbero essere sostituiti nel prossimo futuro. La vecchia applicazione Web è scritta in WebForms e comunica direttamente con questi servizi tramite SOAP e restituisce DataTables
.
Ora sto progettando una nuova applicazione web moderna in uno stile moderno, un client AngularJS che comunica con un'API Web ASP.NET tramite JSON. L'API Web comunica quindi con i servizi WCF tramite SOAP.
In futuro voglio consentire all'API Web di gestire tutte le richieste e andare direttamente al database, ma poiché la logica di business implementata nei servizi WCF è complicata, ci vorrà del tempo per riscriverla e sostituirla.
Ora al problema: sto cercando di semplificare nel prossimo futuro la sostituzione dei servizi WCF con altri archivi di dati, ad es. un altro endpoint, database o qualsiasi altra cosa. Voglio anche semplificare l'analisi della logica aziendale.
Ecco perché ho strutturato l'API Web con repository layer
e service layer
. Il livello del repository ha una comunicazione diretta con l'archiviazione dei dati (servizio WCF, database o qualsiasi altra cosa) e il livello di servizio utilizza quindi il repository ( Dependency Injection
) per ottenere i dati. Non importa da dove riceve i dati. Più tardi posso controllare e strutturare i dati restituiti dall'archivio dati (DataTable a POCO) e poter testare la logica nel livello di servizio con qualche repository fittizio (utilizzando Dependency Injection).
Di seguito è riportato un codice per spiegare dove sto andando con questo. Ma la mia domanda è, ha tutto questo ha senso? Sto rendendo questo troppo complicato e questo potrebbe essere semplificato in ogni modo possibile? Questa semplicità rende questo troppo complicato da mantenere? Il mio obiettivo principale è rendere più semplice possibile passare a un'altra memoria di dati in un secondo momento, ad es. un ORM ed essere in grado di testare la logica nel livello di servizio. E poiché la maggior parte della logica aziendale è implementata in questi servizi WCF (e restituiscono DataTable), voglio avere il controllo dei dati e della struttura restituita al client.
Qualsiasi consiglio è molto apprezzato.
Aggiornamento 20/08/14
Ho creato un factory di repository, quindi i servizi condividono tutti i repository. Ora è facile prendere in giro un repository, aggiungerlo alla fabbrica e creare un provider usando quella fabbrica.
Qualche consiglio è molto apprezzato. Voglio sapere se sto rendendo le cose più complicate di quanto dovrebbero essere.
Quindi sembra questo:
1. Fabbrica del deposito
public class RepositoryFactory
{
private Dictionary<Type, IServiceRepository> repositories;
public RepositoryFactory()
{
this.repositories = new Dictionary<Type, IServiceRepository>();
}
public void AddRepository<T>(IServiceRepository repo) where T : class
{
if (this.repositories.ContainsKey(typeof(T)))
{
this.repositories.Remove(typeof(T));
}
this.repositories.Add(typeof(T), repo);
}
public dynamic GetRepository<T>()
{
if (this.repositories.ContainsKey(typeof(T)))
{
return this.repositories[typeof(T)];
}
throw new RepositoryNotFoundException("No repository found for " + typeof(T).Name);
}
}
Non mi piace molto dynamic
ma non so come recuperare quel repository altrimenti.
2. Repository e servizio
// Service repository interface
// All repository interfaces extend this
public interface IServiceRepository
{
}
// Invoice repository interface
// Makes it easy to mock the repository later on
public interface IInvoiceServiceRepository : IServiceRepository
{
List<Invoice> GetInvoices();
}
// Invoice repository
// Connects to some data storage to retrieve invoices
public class InvoiceServiceRepository : IInvoiceServiceRepository
{
public List<Invoice> GetInvoices()
{
// Get the invoices from somewhere
// This could be a WCF, a database, or whatever
using(InvoiceServiceClient proxy = new InvoiceServiceClient())
{
return proxy.GetInvoices();
}
}
}
// Invoice service
// Service that handles talking to a real or a mock repository
public class InvoiceService
{
// Repository factory
RepositoryFactory repoFactory;
// Default constructor
// Default connects to the real repository
public InvoiceService(RepositoryFactory repo)
{
repoFactory = repo;
}
// Service function that gets all invoices from some repository (mock or real)
public List<Invoice> GetInvoices()
{
// Query the repository
return repoFactory.GetRepository<IInvoiceServiceRepository>().GetInvoices();
}
}