2009-11-08 6 views
79

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

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

Merci

Répondre

82

Il y a 3 façons 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 ainsi vous perdez le contrôle.

  2. Utilisez ChannelFactory avec une interface connue. Cela dépend de la présence d'interfaces locales décrivant le service (le contrat de service). Le gros avantage est que vous pouvez gérer le changement beaucoup plus facilement - vous devez encore 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 plus facilement moqués pour les tests unitaires. Cependant, les interfaces peuvent être écrites pour n'importe quel service, même ceux de REST - jetez un oeil à this Twitter API. Écrivez votre propre proxy - c'est assez facile à faire, en particulier pour les services REST, en utilisant le HttpClient ou WebClient. Cela vous donne le contrôle du grain le plus fin, mais au prix de beaucoup d'API de service dans les 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 pas d'erreur avant l'exécution.

l'option Personnellement, je ne l'ai jamais aimé 1 - se fondant sur le code est généré automatiquement en désordre 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 peut être modifiée mais qui est pénible.

L'option 2 devrait être parfaite, mais les canaux sont un peu trop limitatifs - par exemple completely lose the content of HTTP errors. Cela dit, avoir des interfaces qui décrivent le service est beaucoup plus facile à coder et à maintenir. J'utilise ChannelFactory avec la méthode MetadataResolver.Resolve.

+2

@MurHaf Nope - cette réponse est entièrement mon propre travail. J'attribue TOUJOURS les contributions des autres. J'ai écrit cette réponse basée sur des années de travail avec les services SOAP dans .Net à divers travaux. Cet article que vous liez à partir de Mars 2013, alors que ma réponse a été écrite en Avril 2010 - 3 ans avant! Si le plagiat a eu lieu, il m'a copié. Vous devriez vérifier les dates avant de faire des accusations, car c'est très facile à faire. – Keith

+0

@MurHaf Nous ne sommes même pas arrivés aux mêmes conclusions - cet article recommande la génération automatique d'un proxy (option 1) comme «simple». Je le décris comme facile à mettre en place, mais désordonné et douloureux à maintenir. Il ne parle même pas d'écrire son propre proxy (option 3). – Keith

+1

Je pense que SvcUtil devrait aussi être mentionné, car c'est l'une des façons les plus courantes d '"écrire" un client. –

11

Eh bien pour pouvoir utiliser ChannelFactory<T> vous devez être prêt à partager les assemblées de contrat entre le service et le client. Si cela vous convient, ChannelFactory<T> peut vous faire gagner du temps.

+2

Ce n'est pas vrai. –

+0

@Charles - pouvez-vous expliquer pourquoi ce n'est pas vrai? –

+5

@Aran: Je pense que ce que veut dire Andrew est correct - si vous ne voulez pas générer de fac-similés des classes de contrat, alors vous devriez avoir accès aux originaux. C'est vrai que d'une manière ou d'une autre, vous devez avoir ces classes de contrat. Vous pouvez les générer, les écrire manuellement ou obtenir le code source du service (s'il est dans la même langue). Partager des assemblages est le moyen le plus simple, mais ce n'est pas toujours possible. (Peut-être que je prends juste Andrew littéralement, mais la clarté est importante ici.) –

8

Le proxy va construire des fonctions asynchrones pour lesquelles il est plutôt sympa.

+2

oui - dans le même temps, à la fois «Ajouter une référence de service» de Visual Studio et svcutil.exe sur la ligne de commande abattre votre config au-delà de la reconnaissance .... au moins avec svcutil.exe, vous pouvez définir un "/ noconfig" switch ..... –

+1

ChannelFactory fournit également des méthodes asynchrones: http://msdn.microsoft.com/fr-fr/library/ms731177.aspx Mais je préfère utiliser un template T4 pour créer une classe asynchrone en utilisant ThreadPool qui sera invoquer des méthodes synchrones. – SandRock

+0

Qu'est-ce qu'un modèle T4? – TheWommies

20

La configuration du client est un problème, alors j'obtiens mon ServiceEndpoint du serveur. Lorsque vous utilisez ChannelFactory (Of T), T est le contrat d'origine que vous pouvez obtenir 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 de 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 principal objectif de l'utilisation de ChannelFactory était de me 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, les availableBindings sont vérifiés à utiliser net.tcp ou net.pipe si elle est disponible. De cette façon, je peux utiliser la meilleure reliure disponible pour mes besoins. Je ne compte que sur le fait qu'un point de terminaison de métadonnées existe sur le serveur.

J'espère que cette aide

BTW, cela se fait à l'aide de .NET 3.5. Cependant, cela fonctionne aussi avec 4.0.

+0

Des trucs géniaux. J'utilise aussi MetadataResolver.Resolve pour config mais je n'ai pas pensé à résoudre la liaison du serveur. Très bon point! –

+0

upvote pour mentionner 'Le point principal de l'utilisation de ChannelFactory pour se débarrasser de la configuration du client WCF' – Kurubaran

7

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

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

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

2

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 compile mais le contrat de service est cassé. Je suggère définitivement d'utiliser un ChannelFactory chaque fois que possible, vous rendre la vie beaucoup plus facile.

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.