WCF ChannelFactory a generowanie serwera proxy

82

Zastanawiasz się tylko, w jakich okolicznościach wolisz generować serwer proxy z usługi WCF, gdy możesz po prostu wywoływać wywołania przy użyciu ChannelFactory?

W ten sposób nie będziesz musiał generować serwera proxy i martwić się o jego regenerację po zaktualizowaniu serwera?

Dzięki

TheWommies
źródło
Zawsze używaj ChannelFactory. Nie mogę tego powiedzieć wystarczająco mocno.
tom redfern

Odpowiedzi:

88

Istnieją 3 podstawowe sposoby tworzenia klienta WCF:

  1. Pozwól programowi Visual Studio wygenerować serwer proxy. To automatycznie generuje kod, który łączy się z usługą, odczytując WSDL. Jeśli usługa ulegnie zmianie z jakiegokolwiek powodu, musisz ją zregenerować. Dużą zaletą tego jest to, że jest łatwy w konfiguracji - VS ma kreatora i wszystko działa automatycznie. Wadą jest to, że polegasz na VS, aby wykonać całą ciężką pracę za Ciebie, przez co tracisz kontrolę.

  2. Używaj ChannelFactoryze znanym interfejsem. Zależy to od posiadania lokalnych interfejsów opisujących usługę (kontrakt serwisowy). Dużą zaletą jest to, że można łatwiej zarządzać zmianami - nadal musisz rekompilować i naprawiać zmiany, ale teraz nie regenerujesz kodu, tylko odwołujesz się do nowych interfejsów. Często jest to używane, gdy kontrolujesz zarówno serwer, jak i klienta, ponieważ oba mogą być znacznie łatwiejsze do podrobienia na potrzeby testów jednostkowych. Jednak interfejsy można napisać dla dowolnej usługi, nawet REST - spójrz na to Twitter API .

  3. Napisz własne proxy - jest to dość łatwe, szczególnie w przypadku usług REST, przy użyciu HttpClientlub WebClient. Zapewnia to najdokładniejszą kontrolę ziarna, ale kosztem wielu interfejsów API usług znajdujących się w łańcuchach. Na przykład: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content;- jeśli szczegóły API ulegną zmianie, nie napotkasz błędu do czasu uruchomienia.

Osobiście nigdy nie lubiłem opcji 1 - poleganie na automatycznie generowanym kodzie jest bałaganiarskie i traci zbyt dużą kontrolę. Poza tym często stwarza problemy z serializacją - w rezultacie otrzymuję dwie identyczne klasy (jedną w kodzie serwera, jedną generowaną automatycznie), które można uporządkować, ale jest to uciążliwe.

Opcja 2 powinna być idealna, ale kanały są trochę zbyt ograniczające - na przykład całkowicie tracą zawartość błędów HTTP . To powiedziawszy, posiadanie interfejsów opisujących usługę jest znacznie łatwiejsze do kodowania i utrzymania.

Keith
źródło
4
@MurHaf Nie - ta odpowiedź jest całkowicie moją własną pracą. ZAWSZE przypisuję wkład innych. Napisałem tę odpowiedź na podstawie wielu lat pracy z usługami SOAP w .Net na różnych stanowiskach. Ten artykuł, do którego odsyłasz, pochodzi z marca 2013 r., Podczas gdy moja odpowiedź została napisana w kwietniu 2010 r. - 3 lata wcześniej! Jeśli doszło do plagiatu, skopiował mnie. Powinieneś sprawdzić daty przed postawieniem zarzutów, ponieważ jest to bardzo łatwe.
Keith
@MurHaf nawet nie doszliśmy do tych samych wniosków - ten artykuł zaleca automatyczne generowanie proxy (opcja 1) jako „proste”. Opisuję to jako łatwe w konfiguracji, ale niechlujne i trudne w utrzymaniu. Nie rozmawia nawet o napisaniu własnego proxy (opcja 3).
Keith
1
Myślę, że należy również wspomnieć o SvcUtil, ponieważ jest to jeden z najczęstszych sposobów „pisania” klienta.
Mare Infinitus
21

Używam ChannelFactory wraz z metodą MetadataResolver.Resolve. Konfiguracja klienta jest kłopotliwa, więc pobieram ServiceEndpoint z serwera.

W przypadku korzystania z ChannelFactory (Of T) T jest oryginalną umową, którą można uzyskać z odwołania w projekcie lub wygenerowaną instancją kontraktu. W niektórych projektach wygenerowałem kod z odwołania do usługi, ponieważ nie mogłem dodać odwołania do biblioteki DLL kontraktu. Możesz nawet wygenerować kontrakt asynchroniczny z odwołaniem do usługi i użyć tego interfejsu kontraktu z ChannelFactory.

Głównym celem korzystania z ChannelFactory było pozbycie się informacji o konfiguracji klienta WCF. W poniższym przykładowym kodzie można zobaczyć, jak osiągnąć klienta WCF bez konfiguracji.

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

W moim ostatnim projekcie, availableBindings są sprawdzane pod kątem używania net.tcp lub net.pipe, jeśli są dostępne. W ten sposób mogę użyć najlepszego dostępnego wiązania dla moich potrzeb. Opieram się tylko na fakcie, że punkt końcowy metadanych istnieje na serwerze.

mam nadzieję, że to pomoże

Przy okazji, odbywa się to za pomocą platformy .NET 3.5. Jednak działa również z 4.0.

Jean-Michel Bezeau
źródło
Niesamowite rzeczy. Używam MetadataResolver.Resolve również do konfiguracji, ale nie myślałem o rozwiązaniu wiązania z serwera. Bardzo dobra uwaga!
Sleeper Smith
głos za wzmiankąThe main point of using ChannelFactory to get rid of the WCF client config
Kurubaran
11

Cóż, aby z niego skorzystać ChannelFactory<T>, musisz chcieć udostępniać zestawy kontraktowe między usługą a klientem. Jeśli nie masz nic przeciwko, ChannelFactory<T>możesz zaoszczędzić trochę czasu.

Andrew Hare
źródło
@Charles - czy możesz wyjaśnić, dlaczego to nieprawda?
Aran Mulholland
6
@Aran: Myślę, że to, co Andrew ma na myśli, jest poprawne - że jeśli nie chcesz generować faksymile klas kontraktowych, musisz mieć dostęp do oryginałów. To prawda, że ​​tak czy inaczej musisz mieć te klasy kontraktowe. Możesz je wygenerować, napisać ręcznie lub pobrać kod źródłowy usługi (jeśli jest w tym samym języku). Udostępnianie zestawów jest najłatwiejszym sposobem, ale nie zawsze jest to możliwe. (Może po prostu
traktuję
2
@Charles ok, więc mówisz, że możesz użyć ChannelFactory <T>, nawet jeśli nie miałeś dostępu do zestawów ręcznie kodując interfejs T, a następnie używając tego.
Aran Mulholland
1
@Aran: tak, ręcznie programując lub używając narzędzia takiego jak svcutil (zakładając, że usługa jest uruchomiona i dostępna).
Igby Largeman,
9

Proxy zbuduje funkcje asynchroniczne, co jest miłe.

Aaron Fischer
źródło
2
tak - w tym samym czasie zarówno program Visual Studio „Add Service Reference”, jak i svcutil.exe w wierszu poleceń niszczą Twoją konfigurację nie do poznania… przynajmniej w przypadku svcutil.exe można zdefiniować przełącznik „/ noconfig” .....
marc_s
1
ChannelFactory udostępnia również metody asynchroniczne: msdn.microsoft.com/en-us/library/ms731177.aspx Ale wolę używać szablonu T4 do tworzenia klasy asynchronicznej za pomocą ThreadPool, która będzie wywoływać metody synchroniczne.
SandRock,
1
Jako aktualizacja: w .NET 4.5 ChannelFactory <T> obsługuje również funkcje asynchroniczne oparte na zadaniach.
gimpf
8

Moja odpowiedź jest swego rodzaju podsumowaniem odpowiedzi Keitha i Andrew Hare'a .

Jeśli nie kontrolujesz serwera, ale masz tylko WSDL / URL, wygeneruj proxy za pomocą Visual Studio lub svcutil. (Zauważ, że Visual Studio czasami zawodziło, kiedy svcutil działa lepiej).

Kiedy kontrolujesz zarówno serwer, jak i klienta, udostępniaj interfejsy / kontrakty i wywołuj ChannelFactory
.

Michael Freidgeim
źródło
2

Nie chodzi tylko o oszczędność czasu. Korzystanie z serwera proxy wygenerowanego przez WSDL jest niebezpieczne, ponieważ jeśli zapomnisz zaktualizować odwołanie do usługi, możesz pozostawić rozwiązanie w niespójnym stanie. Wszystko się kompiluje, ale umowa serwisowa jest zepsuta. Zdecydowanie sugeruję korzystanie z ChannelFactory, gdy tylko jest to możliwe, aby ułatwić sobie życie.

Możliwą alternatywą może być napisanie skryptu prebuild, który wywołuje narzędzie SVCUtil w celu utworzenia proxy za każdym razem, gdy budujesz swój projekt, ale w każdym razie ChannelFactory jest znacznie bardziej schludny i elegancki.

Paolo Costa
źródło