Best practice MVVM con il client WPF e il servizio duplex WCF

5

Ho pensato a come progettare la mia applicazione WPF, che riceve i dati da un servizio duplex WCF, ma ho paura dell'over engineering.

Ho pensato di astrarre completamente la comunicazione WCF dal client WPF creando una libreria "client proxy" che implementa internamente le interfacce di servizio e di callback.

In questo modo non devo creare la classe di callback nell'applicazione WPF, ma sottoscrivere gli eventi nel client proxy che vengono richiamati quando i metodi di callback in esso sono chiamati dal servizio. Questo mi permetterebbe anche di nascondere il riferimento al servizio da WPF.

Quindi in WPF, tutto ciò che farò è:

var client = new ApiClient(); //This is the client library
var stuff = client.GetStuff(); //Some service method
client.StuffDeleted += OnStuffDeleted; //Event that is invoked by library on callback

Probabilmente creerei un'istanza del client una sola volta come oggetto Singleton per tutti i ViewModels da chiamare.

Quindi ho pensato di poterlo fare ulteriormente creando classi "Model" che sono quasi identiche alle classi generate dai servizi di riferimento WCF (contratti dati), aggiungendo un altro layer al client proxy e usando automapper per creare i miei modelli , quindi restituirli a WPF invece delle classi di contratto dati.

Ho immaginato che in questo modo avrei ottenuto una separazione completa dal servizio WCF e disporre di un livello aggiuntivo mi avrebbe consentito di aggiungere metadati ai miei modelli prima di restituirli, quindi nel lato WPF userò questi Modelli per costruire il ViewModel che è pensato solo per visualizzare / legare.

Avere un client di questo tipo semplificherebbe anche la centralizzazione della logica aziendale, la gestione degli errori e rendere più semplice il test delle unità poiché il client WCF è un singolo componente indipendente.

Il problema è che ho paura di sovrascrivere questo. Il database ha entità EF, il servizio WCF ha le sue classi DTO, quindi vorrei avere Models e quindi ViewModels. Ho anche notato che le classi generate da WCF implementano l'interfaccia INotifyPropertyChanged, il che mi fa pensare che dovevano essere usati come modelli (o per inviare aggiornamenti al servizio?).

Cercherò di riassumere le mie domande principali nei punti elenco:

  • In M-V-VM, è buona norma utilizzare le classi generiche di riferimento del servizio come Modelli?
  • C'è molto vantaggio nell'estrarre completamente WCF da WPF con un client proxy?
    • I metodi di callback invocheranno gli eventi a cui WPF è iscritto
  • Perché le classi di riferimento del servizio generato implementano INotifyPropertyChanged?

Questo design è eccessivo?

Grazie mille.

UPDATE:

Visualizzazione di ciò che sto cercando di fare:

Come si può vedere, il client Proxy nel mezzo ha 2 livelli (classi):

La prima classe è ciò che WPF istanzia come un Singleton e usa per recuperare le classi del modello.

La seconda classe è un wrapper attorno al client di riferimento del servizio e viene chiamata dal primo livello. Questo è puramente a scopo di accesso ai dati.

Non ho aggiunto i metodi di callback che saranno gli eventi a cui WPF si abbona.

    
posta Shahin Dohan 07.11.2016 - 22:16
fonte

1 risposta

1

Ho avuto una situazione come questa in passato, e alla fine abbiamo creato un layer modello WPF separato per l'applicazione.

Non sono sicuro di quanto è cambiato da allora, tuttavia le nostre ragioni erano:

  • Volevamo proprietà di sola lettura nell'applicazione e le DTO generate da DataContracts dovevano essere in lettura / scrittura

  • Alcune classi erano molto grandi, ma il modello dell'interfaccia utente richiedeva solo una sezione molto più piccola dei dati.

  • Alcune proprietà sul livello dell'interfaccia utente avevano una logica personalizzata. Ad esempio, volevamo mantenere la proprietà db come int di 123, tuttavia per scopi di interfaccia utente volevamo una stringa di "000123"

  • Volevamo mantenere aperta la possibilità in futuro di poter cambiare lo stack tecnologico di un livello, ad esempio sostituire il layer WCF o EF con qualche altro alternativo. Separandoli, dovremmo solo riscrivere un livello invece di tutto nell'applicazione.

  • Volevamo aggiungere un livello di crittografia ad alcuni dati, quindi i dati sarebbero stati crittografati a riposo o per il trasferimento ... Non ricordo molto di questo requisito, ma ha influito sulla nostra decisione.

Il nostro risultato finale era:

  • Progetto per modelli WPF che crea solo i modelli di interfaccia utente utilizzati dall'applicazione, utilizzando le proprietà, i tipi di dati e l'ambito corretti richiesti dall'interfaccia utente.

  • Progetto per Data Access Layer, che si occuperà di convertire i modelli WPF in modelli DTO o EF per il trasferimento a livello di database. In realtà abbiamo usato AutoMapper anche per questo.

  • Il progetto WCF attuale, con classi generate automaticamente da WCF

  • Il progetto EF effettivo, con modelli EF e procedure auto-generati

Se ricordo correttamente, dal livello dell'applicazione WPF, faremmo qualcosa del tipo:

ISomeService service = DAL.SomeService();
ISomeModel stuff = service.GetStuff();

Il DAL restituirebbe una classe di servizio che incontrava un'interfaccia. Se avessimo mai voluto sostituire il livello di servizio con qualcos'altro, avremmo potuto senza influire sul resto dell'applicazione WPF.

Inoltre, ISomeModel potrebbe implementare elementi specifici per l'applicazione WPF stessa, come logica o eventi personalizzati. Non doveva essere legato all'oggetto di dati che inviamo / riceviamo al database.

    
risposta data 08.12.2016 - 17:37
fonte

Leggi altre domande sui tag