2009-12-11 13 views
6

Ho un'applicazione WPF che finora è stata solo client, ma ora sto lavorando per suddividerla in un lato client e server. In questo lavoro sto introducendo WCF per la comunicazione client-server. La mia applicazione ha diversi progetti e sono necessari riferimenti di servizio da più di uno di questi.Struttura dell'applicazione utilizzando WCF

Lo sforzo iniziale nel fare la separazione è fare tutto "in modo diretto". Tutti i progetti che devono comunicare con un servizio ricevono un riferimento al servizio, e così anche il progetto principale dell'applicazione WPF - per ottenere l'app.config lì. Trovo che questo si trasformi in un casino piuttosto rapidamente, e non riesco a immaginare che questa sia la tipica architettura usata dalle persone? Ho anche riscontrato problemi con il fatto che ognuno dei riferimenti al servizio genera una nuova implementazione delle classi DataContract - quindi non esiste una comprensione comune delle classi DataContract su più progetti. Ho alcune classi ViewModel in un progetto e un altro progetto che installa alcuni ViewModel. Mi piacerebbe passare l'oggetto ricevuto dal servizio, ma non posso come la rappresentazione generata lato client dell'oggetto ricevuto differisce in ogni progetto.

Quindi, c'è un modo consigliato di strutturare tali separazioni client/server utilizzando WCF? O principi da seguire? Sto pensando a un progetto Proxy comune utilizzato sul lato client che esegue la comunicazione con i servizi, avvolge i dati ricevuti e restituisce i dati su un modulo ben noto alle librerie client. Dovrebbe dare solo un riferimento al servizio, e credo che mi occorresse solo App.config nel progetto wpfApp? Ha senso ciò?

risposta

16

mi piace di strutturare le mie soluzioni WCF come questo:

Contratti (libreria di classi)
contiene tutti i contratti di servizio, le operazioni, di guasto e di dati.Possono essere condivisi tra server e client in uno scenario puro NET-to-NET

implementazione Servizio (libreria di classi)
contiene il codice per implementare i servizi, e di tutti i metodi di supporto/helper necessario per raggiungere questo obiettivo . Nient'altro.

host del servizio (s) (opzionale - può essere WinForms, console di App, servizio NT)
Contiene host del servizio (s) per il debug/test, o, eventualmente, anche per la produzione.

Questo fondamentalmente mi dà il lato server delle cose.

Sul lato client:

proxy client (libreria di classi)
mi piace il mio pacchetto di proxy client in una libreria di classe separata, in modo che possano essere riutilizzati da più applicazioni client effettivi. Questo può essere fatto usando svcutil o "Aggiungi riferimento al servizio" e modificando manualmente l'orribile app.config risultante, oppure eseguendo manualmente i proxy client (quando si condivide l'assembly dei contratti) usando i costrutti ClientBase<T> o ChannelFactory<T>.

1-n clienti attuali (qualsiasi tipo di applicazione)
in genere solo come riferimento il gruppo proxy client, o forse l'assemblea contratti, anche se quest'ultimo è stato condiviso. Può trattarsi di ASP.NET, WPF, Winforms, app per console, altri servizi.

In questo modo; Ho un layout curato e pulito, lo uso costantemente e ancora, e penso davvero che questo abbia reso il mio codice più pulito e più facile da mantenere.

Questo è stato ispirato da Miguel Castro Extreme WCF screen cast su DotNet Rocks TV con Carl Franklin - cast schermo altamente raccomandato!

+0

Grazie per la risposta molto bella!Alcune domande: Avere un host di servizio è necessario avviare sia l'host che il client all'avvio della tua app? O c'è un modo per aggirare questo? Per quanto riguarda i proxy client - quale preferiresti? Manuale impl suona più coerente in quanto non si ha a che fare con riferimenti di servizio che non sono aggiornati. – stiank81

+0

@bambuska: certo, è necessario avviare sia l'host del servizio che il client da testare; selezionare "lanciare più progetti" in Visual Studio per ottenere questo risultato: è possibile avviare sia l'host del servizio che il client quando si preme F5. –

+1

Proxy client: mi piace il controllo totale che ho quando eseguo l'implementazione manuale dei proxy client - questo ** richiede ** anche se posso condividere il contratto tra server e client (poiché l'installazione manuale dei proxy client deve avere accesso –

1

Dipende. WCF è un grande framework e ha lo scopo di coprire molti scenari diversi.

Ma per una semplice applicazione come la tua, se non si cura di cose come Java interoperabilità o servizi web generici interoperabilità, questo è quello che faccio:

classi Tutte DataContract e interfacce ServiceContract andare in una libreria (o librerie) che è condivisa tra il client e il server. Nota che probabilmente non dovresti decorare il tuo servizio Implementazione con ServiceContract, dovresti creare un'interfaccia separata con gli attributi ServiceContract che potresti inserire in un assembly condiviso.

Quindi sembra che tu stia facendo tutto bene. Ciò di cui probabilmente non hai bisogno è di generare automaticamente i proxy in questo caso. Ti sta solo causando dolore. Quindi non usare la finestra di dialogo Aggiungi riferimento servizio per quello che stai facendo. Basta includere gli assembly DataContract condivisi e utilizzare ChannelFactory per ottenere un proxy per l'interfaccia di servizio definita nella libreria condivisa. Questo ti impedisce anche di continuare a rigenerare il proxy in Visual Studio, che, per qualsiasi progetto di dimensioni decenti, diventa MOLTO VELOCE.

Se si sta percorrendo questa rotta, è anche possibile eliminare l'endpoint MetaDataExchange, poiché è necessario solo descrivere il servizio al client. Poiché fai tutto in un assembly condiviso, non hai bisogno della descrizione del servizio, dal momento che hai già la descrizione del servizio in forma di codice.

+0

Grazie! Sembra molto attraente. I proxy generati automaticamente hanno già causato dolore ... Sto effettivamente provando un'implementazione simile a quella che hai già descritto, ma si è fermato quando volevo servizi asincroni. Posso usare facilmente ChannelFactory per generare anche servizi asincroni? – stiank81

+0

Oh, e JavaInterop ecc non è affatto rilevante. Questo sarà tutto .net to .net! Avendo il DataContracts in una libreria condivisa posso effettivamente restituire ad es. un oggetto MyClass da un servizio, e sarà lo stesso identico tipo ricevuto? – stiank81

+0

Sì: http://msdn.microsoft.com/en-us/library/bb885132.aspx –

1

La struttura solito che uso è:

comune - contiene interfacce,-contratti dati, contratti di servizio, classi astratte, ecc; Client - riferimenti Comune, contiene una classe proxy del server; Server - riferimenti Common, contiene classi di implementazione effettive;

+1

concordato. Anche se spesso farei che la libreria comune includa DTO che possono essere usati su entrambi i lati del servizio e quindi non usare le classi proxy generate. – asgerhallas

+0

Sembra che io debba avere un progetto comune per le cose condivise ..! Stai usando proxy autogenerati o li ometti, come @asgerhallas? Certo, penso che mi piacerebbe non usarli se posso. Hanno già causato troppo dolore. – stiank81

+1

Derivamo la classe proxy da ClientBase e implementano l'interfaccia per inoltrare le chiamate al canale. – Goran

Problemi correlati