2010-06-25 4 views
36

Ma première question donc espérons qu'il convient:WCF Service de référence génère sa propre interface contrat, ne sera pas réutiliser le mien

ensemble d'interface partagée - je une assemblée « partagée » qui a une interface, permettent de faire appel de il IDocRepository. Il est marqué [ServiceContract] et il existe plusieurs méthodes marquées [OperationContract].

Assemblages d'implémentation WCF - J'ai deux projets de service WCF, chacun référençant l'assembly partagé, chacun implémentant cette interface en tant que service WCF.

Assemblage du consommateur - Enfin, j'ai un projet 'client', référençant également l'assembly partagé, avec une référence à chacun des deux services WCF.

Cependant, les références de service générées dans l'ensemble de consommateurs tirent d'une version générée automatiquement de l'interface:

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

Ce que j'attendais
j'aurais espéré que les deux références seraient plutôt hériter automatiquement l'interface que j'ai définie, que l'assembly consommateur/client fait également référence. Un peu comme la réutilisation des classes qu'il fournit pour les types de paramètre et de retour, mais pour l'interface de service.

Pourquoi
Alors que je peux créer une instance de proxy de référence soit de service et de le jeter à mon type d'interface.

donc je pourrais modifier le code généré par la main à chaque fois, mais il devrait y avoir une meilleure façon ...?

(edit: Je n'ai « types de réutilisation dans les assemblages référencés » et «types de réutilisation dans tous les ensembles référencés de options sélectionnées pour les références de service)

Répondre

44

« types de réutilisation dans les assemblages référencés » ne vous permet de réutiliser les contrats de données, pas de contrats de service. Si vous souhaitez partager des contrats de service, vous n'avez pas besoin d'utiliser "Ajouter une référence de service". Vous pouvez utiliser directement ChannelFactory.

// 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'objet de canal mettra également en œuvre ICommunicationObject, donc vous pouvez jeter si vous avez besoin d'appeler des méthodes comme Open() ou Fermer().

+1

Grande solution, merci –

+0

J'y allais avec la deuxième option, mais j'ai l'erreur qu'il doit y avoir une EndpointAddress spécifiée. J'ai un point de terminaison mis en place dans le fichier de configuration, avec le même contrat (interface) spécifié, mais il ne semble pas regarder là-bas? Pouvez-vous aider? –

+2

Nevermind; vous devez transmettre le nom de la configuration du noeud final au constructeur ChannelFactory <>. –

4

Lorsque vous créez la référence de service, il y a une boîte, vous pouvez cochez pour le réutiliser les définitions partagées. Assurez-vous que le projet client référence déjà l'assembly partagé, ajoutez à nouveau la référence de service et vérifiez attentivement toutes les options.

Si cela ne fonctionne toujours pas, vérifiez la liaison que vous utilisez. Je me souviens vaguement que la liaison HTTP de base ne supporterait pas la réutilisation des types?

+0

Salut David, merci pour le commentaire! - J'ai fait exactement cela, j'aurais dû le mentionner. :) 'Réutiliser les types dans les assemblages référencés' est vérifié, et je l'ai essayé avec 'Réutiliser les types dans tous les assemblages référencés', et 'Réutiliser les types dans les assemblages référencés spécifiés' tout en sélectionnant manuellement l'assemblage en question - les deux avec le même résultat comme ci-dessus). –

+0

Seul le problème avec cette route est si vous voulez référencer 2 services avec la même lib partagée; vous obtenez des objets dupliqués. – eschneider

+0

@eschneider - Je ne vois pas comment c'est le cas, c'est ce que fait l'option 'Réutiliser ...', ça arrête la duplication des classes ('objets') en utilisant les classes référencées existantes - n'est-ce pas? Cependant, je vois des interfaces dupliquées, ce qui est le problème que j'ai décrit dans ma question :). –

2

Il y a une autre bonne option, si vous voulez continuer à utiliser le générateur de proxy pour ses fonctionnalités limitées, mais-peu-utiles ... Utiliser une classe partielle:

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

Assurez-vous que la procuration générer le code de la même manière que votre contrat de service le définit, c'est-à-dire s'il utilise 'Liste', utilisez également cette option dans Configurer les références de service.En d'autres termes, assurez-vous que l'interface de service générée est exactement égale à votre véritable interface de service et que le code ci-dessus devrait fonctionner, et pour mettre à jour la référence, cliquez avec le bouton droit de la souris. Visual Studio ne prend pas en charge la réutilisation de votre interface existante lors de la génération des classes de proxy pour vous.

+0

Se sent comme un hack mais fonctionne! –

2

Les types de réutilisation ne réutiliseront pas l'interface de contrat comme indiqué par Quartermeister.

Nous l'avons résolu avec héritage. Très similaire à l'idée de classe partielle ci-dessus suggérée par Jester Software.

Voilà comment nous résolu le problème:

Dans le projet de votre client vient de créer une référence de service que vous auriez fait. Ensuite, ajoutez une classe qui sert de remplacement pour le client:

internal class MyServiceProxy : MyServiceClient, MyLogicNamespace.IMyService 
{} 

Cette classe hérite de la MyServiceClient générée, mais précise que ce client n'implémente l'interface originale.

(je vous suggère de les mettre dans un dossier nommé « ServiceProxies »)

Si la classe MyServiceClient contient des méthodes qui ne correspondent pas à l'interface originale, alors vous pouvez les ajouter à cette procuration et faire la conversion en code. Ensuite, utilisez simplement MyServiceProxy où vous auriez utilisé MyServiceClient.

Questions connexes