web-dev-qa-db-fra.com

WCF ChannelFactory vs génération de proxy

Vous vous demandez simplement dans quelles circonstances préféreriez-vous générer un proxy à partir d'un service WCF lorsque vous pouvez simplement appeler des appels à l'aide de ChannelFactory?

De cette façon, vous n'aurez pas à générer un proxy et à vous soucier de régénérer un proxy lorsque le serveur est mis à jour?

Merci

81
TheWommies

Il existe 3 méthodes de base pour créer un client WCF:

  1. Laissez Visual Studio générer votre proxy. Cette auto génère du code qui se connecte au service en lisant le WSDL. Si le service change pour une raison quelconque, vous devez le régénérer. Le gros avantage de ceci est qu'il est facile à configurer - VS a un assistant et tout est automatique. L'inconvénient est que vous comptez sur VS pour faire tout le travail dur pour vous, et donc vous perdez le contrôle.

  2. Utilisez ChannelFactory avec une interface connue. Pour cela, vous devez disposer d'interfaces locales décrivant le service (le contrat de service). Le gros avantage est qu'il peut gérer le changement beaucoup plus facilement - vous devez toujours recompiler et corriger les modifications, mais maintenant vous ne régénérez pas le code, vous faites référence aux nouvelles interfaces. Généralement, cela est utilisé lorsque vous contrôlez à la fois le serveur et le client, car les deux peuvent être beaucoup plus facilement simulés pour les tests unitaires. Cependant, les interfaces peuvent être écrites pour n'importe quel service, même REST ceux - jetez un œil à cette API Twitter .

  3. Écrivez votre propre proxy - c'est assez facile à faire, en particulier pour les services REST, en utilisant HttpClient ou WebClient. Cela vous donne le contrôle le plus fin du grain , mais au prix de nombreuses API de service dans des chaînes. Par exemple: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content; - si les détails de l'API changent, vous ne rencontrerez aucune erreur avant l'exécution.

Personnellement, je n'ai jamais aimé l'option 1 - compter sur le code généré automatiquement est désordonné et perd trop de contrôle. De plus, cela crée souvent des problèmes de sérialisation - je me retrouve avec deux classes identiques (une dans le code du serveur, une générée automatiquement) qui peuvent être corrigées mais qui sont pénibles.

L'option 2 devrait être parfaite, mais les canaux sont un peu trop limitatifs - par exemple, ils perdent complètement le contenu des erreurs HTTP . Cela dit, il est beaucoup plus facile de coder et de maintenir des interfaces décrivant le service.

86
Keith

J'utilise ChannelFactory avec la méthode MetadataResolver.Resolve. La configuration du client est un problème, donc j'obtiens mon ServiceEndpoint depuis le serveur.

Lorsque vous utilisez ChannelFactory (Of T), T est soit le contrat d'origine que vous pouvez obtenir à partir d'une référence dans votre projet ou d'une instance de contrat générée. Dans certains projets, j'ai généré le code à partir d'une référence de service car je ne pouvais pas ajouter de référence à la DLL du contrat. Vous pouvez même générer un contrat asynchrone avec la référence de service et utiliser cette interface de contrat avec ChannelFactory.

Le point principal de l'utilisation de ChannelFactory pour moi était de se débarrasser des informations de configuration du client WCF. Dans l'exemple de code ci-dessous, vous pouvez voir comment réaliser un client WCF sans configuration.

Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()

Dans mon projet final, les liens disponibles sont vérifiés pour utiliser net.tcp ou net.pipe s'ils sont disponibles. De cette façon, je peux utiliser la meilleure reliure disponible pour mes besoins. Je m'appuie uniquement sur le fait qu'il existe un point de terminaison de métadonnées sur le serveur.

J'espère que ça aide

BTW, cela se fait en utilisant .NET 3.5. Cependant, cela fonctionne également avec 4.0.

21
Jean-Michel Bezeau

Eh bien, pour utiliser ChannelFactory<T> vous devez être disposé à partager les assemblages contractuels entre le service et le client. Si cela vous convient, alors ChannelFactory<T> peut vous faire gagner du temps.

11
Andrew Hare

Le proxy construira des fonctions asynchrones pour lesquelles c'est un peu Nice.

9
Aaron Fischer

Ma réponse est une sorte de résumé des réponses Keith's et Andrew Hare .

Si vous ne contrôlez pas le serveur, mais que vous disposez uniquement d'un proxy de génération WSDL/URL à l'aide de Visual Studio ou de svcutil. (Notez que Visual Studio a parfois échoué, lorsque svcutil fonctionne mieux).

Lorsque vous contrôlez à la fois le serveur et le client, partagez les interfaces/contrats et appelez ChannelFactory
.

7
Michael Freidgeim

Ce n'est pas seulement une question de temps gagné. L'utilisation du proxy généré par WSDL est dangereuse car si vous oubliez de mettre à jour la référence de service, vous pouvez laisser la solution dans un état incohérent. Tout se compile mais le contrat de service est rompu. Je suggère définitivement d'utiliser une ChannelFactory dans la mesure du possible, vous simplifiez la vie.

Une alternative possible pourrait être d'écrire un script de pré-construction qui appelle l'utilitaire SVCUtil pour créer le proxy à chaque fois que vous construisez votre projet, mais de toute façon ChannelFactory est beaucoup plus soigné et élégant.

2
Paolo Costa