2010-06-25 6 views
36

La mia prima domanda quindi spero è adatto:WCF Service Reference genera la propria interfaccia di contratto, non riutilizzare il mio

assemblaggio interfaccia comune - Ho un assembly 'condiviso', che dispone di un'interfaccia, Chiamiamo it IDocRepository. È contrassegnato con [ServiceContract] e vi sono diversi metodi contrassegnati da [OperationContract].

Insieme di implementazione WCF - Ho due progetti di servizio WCF, ognuno dei quali fa riferimento all'assembly condiviso, ciascuno implementando quell'interfaccia come servizio WCF.

Assemblaggio consumatori - Infine, ho un progetto "client", che fa anche riferimento all'assembly condiviso, con un riferimento a ciascuno dei due servizi WCF.

Tuttavia, i riferimenti dei servizi generati nel montaggio dei consumatori derivano da una versione generata automaticamente dell'interfaccia:

public partial class ExampleClient : System.ServiceModel.ClientBase<SomeNamespace.ExampleSvcRef.IDocRepository>, SomeNamespace.ExampleSvcRef.IDocRepository { 

Quello che mi aspettavo
avrei sperato che i due riferimenti sarebbero invece ereditare automaticamente l'interfaccia che ho definito, che fa riferimento anche all'assembly cliente/cliente. Un po 'come il riutilizzo delle classi che fornisce parametri e tipi di ritorno, ma per l'interfaccia di servizio.

Perché
In modo che posso creare un'istanza di delega di riferimento sia il servizio e il cast al mio tipo di interfaccia.

Così ho potuto modificare il codice generato a mano ogni volta, ma ci dovrebbe essere modo migliore ...?

(edit: Io ho 'tipi riutilizzo in assemblee di riferimento' e 'tipi riutilizzo di tutti gli assembly referenziati' opzioni selezionate per entrambi i riferimenti di servizio)

risposta

44

"Riutilizzare i tipi negli assiemi di riferimento" consente solo di riutilizzare i Contratti di dati, non i Contratti di assistenza. Se si desidera condividere contratti di assistenza, non è necessario utilizzare "Aggiungi riferimento servizio". Puoi semplicemente usare ChannelFactory direttamente.

// Supply the binding and address in code 
Binding binding = new BasicHttpBinding(); 
EndpointAddress address = new EndpointAddress("http://tempuri.org/address"); 
IServiceContract channel = ChannelFactory<IServiceContract>.CreateChannel(binding, address); 

// Or read them from the config file 
ChannelFactory<IServiceContract> channelFactory = new ChannelFactory<IServiceContract>(); 
IServiceContract channel = channelFactory.CreateChannel(); 

L'oggetto canale sarà anche attuare ICommunicationObject, in modo da poter lanciare, se avete bisogno di chiamare metodi come open() o Close().

+1

Ottima soluzione, grazie –

+0

Stavo andando con la seconda opzione, ma ottengo l'errore che deve essere specificato un EndpointAddress. Ho un endpoint impostato nel file di configurazione, con lo stesso contratto (interfaccia) specificato, ma sembra che non ci stia guardando? Puoi aiutare? –

+2

Nevermind; è necessario passare il nome di configurazione dell'endpoint nel costruttore di ChannelFactory <>. –

4

Quando si crea il riferimento al servizio, c'è una scatola che si può selezionare per riutilizzare le definizioni condivise. Assicurarsi che il progetto client stia già facendo riferimento all'assembly condiviso, aggiungere nuovamente il riferimento al servizio e controllare attentamente tutte le opzioni.

Se non funziona ancora, controllare la rilegatura che si utilizza. Ho un vago ricordo che il binding HTTP di base non supporterà il riutilizzo dei tipi?

+0

Ciao David, grazie per il commento! - Ho fatto esattamente questo, avrei dovuto menzionare. :) 'Riutilizza i tipi negli assembly referenziati' è spuntato, e l'ho provato con 'Riutilizzare i tipi in tutti gli assembly di riferimento', e 'Riutilizzare i tipi negli assembly referenziati specificati' mentre selezionavo manualmente l'assembly in questione - entrambi con lo stesso risultato (come sopra). –

+0

Unico problema con quel percorso è se si desidera fare riferimento a 2 servizi con la stessa lib condivisa; ottieni oggetti duplicati. – eschneider

+0

@eschneider - Non vedo come sia, questo è ciò che fa l'opzione 'Riutilizza ...', blocca la duplicazione delle classi ('oggetti') usando le classi di riferimento esistenti - no? Tuttavia vedo interfacce duplicate, che è il problema che ho descritto nella mia domanda :). –

2

C'è un'altra buona opzione, se si desidera continuare a utilizzare il generatore di proxy per la sua funzionalità limitate, ma-po-utili ... Utilizzare una classe parziale:

namespace <same namespace as generated proxy> 
{ 
    public partial class MyClient : <namespace of "real" service contract>.IServiceContract 
    { 
    } 
} 

Assicurarsi che il proxy è generando il codice nello stesso modo in cui il contratto di servizio lo sta definendo, cioè, se sta usando "Elenco", utilizzare tale opzione anche in Configura riferimenti servizio.In altre parole, assicurati che l'interfaccia di servizio generata sia esattamente uguale all'interfaccia di servizio reale e che il codice sopra riportato funzioni e per aggiornare il riferimento che utilizzi, fai clic con il tasto destro del mouse anziché scrivere codice.

+0

Sembra un trucco ma funziona! –

2

Visual Studio non supporta il riutilizzo dell'interfaccia esistente durante la generazione delle classi proxy. I tipi di riutilizzo non riutilizzeranno l'interfaccia del contratto come indicato da Quartermeister.

L'abbiamo risolto con l'ereditarietà. Abbastanza simile all'idea di classe parziale sopra suggerita da Jester Software.

Questo è come abbiamo risolto:

Nel progetto del vostro cliente basta creare un riferimento al servizio, come avresti fatto. Quindi aggiungere una classe che funge da sostituto per il cliente:

internal class MyServiceProxy : MyServiceClient, MyLogicNamespace.IMyService 
{} 

Questa classe eredita dalla MyServiceClient generato ma afferma che quel cliente fa implementare l'interfaccia originale.

(vi consiglio di metterli in una cartella denominata "ServiceProxies")

Se la classe MyServiceClient contiene tutti i metodi che non corrispondono con l'interfaccia originale, allora si possono aggiungere in tale proxy e fare la conversione in codice.

Dopo questo, utilizzare MyServiceProxy dove si sarebbe utilizzato MyServiceClient.

Problemi correlati