WCF ChannelFactory vs Proxy generieren

82

Sie fragen sich nur, unter welchen Umständen Sie einen Proxy aus einem WCF-Dienst generieren möchten, wenn Sie nur Anrufe über die ChannelFactory aufrufen können?

Auf diese Weise müssen Sie keinen Proxy generieren und müssen sich keine Gedanken über die Neuerstellung eines Proxys machen, wenn der Server aktualisiert wird.

Vielen Dank

TheWommies
quelle
Verwenden Sie immer ChannelFactory. Ich kann das nicht stark genug sagen.
Tom Redfern

Antworten:

87

Es gibt drei grundlegende Möglichkeiten, einen WCF-Client zu erstellen:

  1. Lassen Sie Visual Studio Ihren Proxy generieren. Dadurch wird automatisch Code generiert, der durch Lesen der WSDL eine Verbindung zum Dienst herstellt. Wenn sich der Dienst aus irgendeinem Grund ändert, müssen Sie ihn neu generieren. Der große Vorteil davon ist, dass es einfach einzurichten ist - VS hat einen Assistenten und alles ist automatisch. Der Nachteil ist, dass Sie sich darauf verlassen, dass VS die ganze harte Arbeit für Sie erledigt, und dass Sie die Kontrolle verlieren.

  2. Verwendung ChannelFactorymit einer bekannten Schnittstelle. Dies setzt voraus, dass Sie über lokale Schnittstellen verfügen, die den Service (den Servicevertrag) beschreiben. Der große Vorteil ist, dass Änderungen viel einfacher verwaltet werden können - Sie müssen Änderungen immer noch neu kompilieren und korrigieren, aber jetzt generieren Sie keinen Code neu, sondern verweisen auf die neuen Schnittstellen. In der Regel wird dies verwendet, wenn Sie sowohl Server als auch Client steuern, da beide für Unit-Tests viel einfacher verspottet werden können. Die Schnittstellen können jedoch für jeden Dienst geschrieben werden, auch für REST-Dienste. Schauen Sie sich diese Twitter-API an .

  3. Schreiben Sie Ihren eigenen Proxy - dies ist ziemlich einfach, insbesondere für REST-Services, indem Sie das HttpClientoder verwenden WebClient. Dies gibt Ihnen die feinste Kornkontrolle, jedoch auf Kosten vieler Service-APIs in Strings. Zum Beispiel: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content;- Wenn sich die Details der API ändern, tritt erst zur Laufzeit ein Fehler auf.

Persönlich hat mir Option 1 noch nie gefallen - das Verlassen auf den automatisch generierten Code ist chaotisch und verliert zu viel Kontrolle. Außerdem entstehen häufig Serialisierungsprobleme - ich habe zwei identische Klassen (eine im Servercode, eine automatisch generiert), die aufgeräumt werden können, aber schmerzhaft sind.

Option 2 sollte perfekt sein, aber Kanäle sind etwas zu einschränkend - zum Beispiel verlieren sie den Inhalt von HTTP-Fehlern vollständig . Das heißt, Schnittstellen, die den Dienst beschreiben, sind viel einfacher zu codieren und zu warten.

Keith
quelle
3
@ MurHaf Nein - diese Antwort ist ganz meine eigene Arbeit. Ich schreibe immer die Beiträge anderer zu. Ich habe diese Antwort basierend auf jahrelanger Arbeit mit SOAP-Diensten in .Net bei verschiedenen Jobs geschrieben. Der Artikel, auf den Sie verlinken, stammt aus dem März 2013, während meine Antwort im April 2010 geschrieben wurde - 3 Jahre zuvor! Wenn Plagiate aufgetreten sind, hat er mich kopiert. Sie sollten die Daten überprüfen, bevor Sie Anschuldigungen erheben, da dies sehr einfach ist.
Keith
@MurHaf Wir kommen nicht einmal zu den gleichen Schlussfolgerungen - in diesem Artikel wird empfohlen, einen Proxy (Option 1) automatisch als "einfach" zu generieren. Ich beschreibe es als einfach einzurichten, aber chaotisch und schmerzhaft zu pflegen. Er bespricht nicht einmal das Schreiben eines eigenen Proxys (Option 3).
Keith
1
Ich denke, SvcUtil sollte auch erwähnt werden, da dies eine der häufigsten Möglichkeiten ist, einen Client zu "schreiben".
Mare Infinitus
21

Ich verwende ChannelFactory zusammen mit der MetadataResolver.Resolve-Methode. Die Client-Konfiguration ist problematisch, daher erhalte ich meinen ServiceEndpoint vom Server.

Wenn Sie ChannelFactory (Of T) verwenden, ist T entweder der ursprüngliche Vertrag, den Sie aus einer Referenz in Ihrem Projekt oder einer generierten Vertragsinstanz erhalten können. In einigen Projekten habe ich den Code aus einer Servicereferenz generiert, da ich der Vertrags-DLL keinen Verweis hinzufügen konnte. Sie können sogar einen asynchronen Vertrag mit der Servicereferenz erstellen und diese Vertragsschnittstelle mit ChannelFactory verwenden.

Der Hauptpunkt bei der Verwendung von ChannelFactory war für mich, die WCF-Client-Konfigurationsinformationen zu entfernen. Im folgenden Beispielcode sehen Sie, wie Sie einen WCF-Client ohne Konfiguration erreichen.

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()

In meinem letzten Projekt werden die verfügbaren Bindungen überprüft, um net.tcp oder net.pipe zu verwenden, falls verfügbar. Auf diese Weise kann ich die beste verfügbare Bindung für meine Bedürfnisse verwenden. Ich verlasse mich nur auf die Tatsache, dass auf dem Server ein Metadatenendpunkt vorhanden ist.

ich hoffe das hilft

Übrigens geschieht dies mit .NET 3.5. Es funktioniert jedoch auch mit 4.0.

Jean-Michel Bezeau
quelle
Tolles Zeug. Ich verwende MetadataResolver.Resolve auch für die Konfiguration, habe aber nicht daran gedacht, die Bindung vom Server aufzulösen. Sehr guter Punkt!
Sleeper Smith
Upvote für die ErwähnungThe main point of using ChannelFactory to get rid of the WCF client config
Kurubaran
11

Nun, um nutzen zu können ChannelFactory<T>, müssen Sie bereit sein, Vertragsbaugruppen zwischen dem Service und dem Kunden zu teilen. Wenn dies für Sie in Ordnung ist, ChannelFactory<T>können Sie Zeit sparen.

Andrew Hare
quelle
@ Charles - kannst du erklären, warum das nicht stimmt?
Aran Mulholland
6
@Aran: Ich denke, was Andrew damit sagen will, ist richtig - wenn Sie keine Faksimiles der Vertragsklassen erstellen möchten, müssen Sie Zugriff auf die Originale haben. Es ist wahr, dass Sie auf die eine oder andere Weise diese Vertragsklassen haben müssen. Sie können sie generieren, von Hand schreiben oder den Service-Quellcode abrufen (sofern er in derselben Sprache vorliegt). Das Teilen von Assemblys ist der einfachste Weg, aber das ist nicht immer möglich. (Vielleicht nehme ich Andrew einfach zu wörtlich, aber Klarheit ist hier wichtig.)
Igby Largeman
2
@Charles ok, Sie sagen also, dass Sie ChannelFactory <T> verwenden könnten, selbst wenn Sie keinen Zugriff auf die Assemblys hätten, indem Sie die Schnittstelle von T von Hand codieren und diese dann verwenden.
Aran Mulholland
1
@Aran: Ja, entweder durch Handcodierung oder mithilfe eines Tools wie svcutil (vorausgesetzt, der Dienst wird ausgeführt und ist verfügbar).
Igby Largeman
9

Der Proxy erstellt asynchrone Funktionen, für die es nett ist.

Aaron Fischer
quelle
2
Ja, gleichzeitig können sowohl Visual Studios "Add Service Reference" als auch svcutil.exe in der Befehlszeile Ihre Konfiguration bis zur Unkenntlichkeit schlachten. Zumindest mit svcutil.exe können Sie einen "/ noconfig" -Schalter definieren .....
marc_s
1
ChannelFactory bietet auch asynchrone Methoden: msdn.microsoft.com/en-us/library/ms731177.aspx Ich bevorzuge jedoch die Verwendung einer T4-Vorlage, um eine asynchrone Klasse mit ThreadPool zu erstellen, die synchrone Methoden aufruft.
SandRock
1
Als Update: Mit .NET 4.5 unterstützt ChannelFactory <T> auch aufgabenbasierte asynchrone Funktionen.
Gimpf
8

Meine Antwort ist eine Art Zusammenfassung der Antworten von Keith und Andrew Hare .

Wenn Sie den Server nicht steuern, sondern nur über WSDL / URL verfügen, generieren Sie einen Proxy mit Visual Studio oder svcutil. (Beachten Sie, dass Visual Studio manchmal fehlgeschlagen ist, wenn svcutil besser funktioniert.)

Wenn Sie sowohl Server als auch Client steuern, geben Sie Schnittstellen / Verträge frei und rufen Sie ChannelFactory auf
.

Michael Freidgeim
quelle
2

Es ist nicht nur eine Frage der Zeitersparnis. Die Verwendung des von WSDL generierten Proxys ist gefährlich, da Sie die Lösung in einem inkonsistenten Zustand belassen können, wenn Sie vergessen, die Dienstreferenz zu aktualisieren. Alles wird kompiliert, aber der Servicevertrag ist gebrochen. Ich empfehle auf jeden Fall, wann immer möglich eine ChannelFactory zu verwenden, um Ihnen das Leben zu erleichtern.

Eine mögliche Alternative könnte darin bestehen, ein vorgefertigtes Skript zu schreiben, das das Dienstprogramm SVCUtil aufruft, um den Proxy jedes Mal zu erstellen, wenn Sie Ihr Projekt erstellen. Trotzdem ist ChannelFactory viel ordentlicher und eleganter.

Paolo Costa
quelle