WCF ChannelFactory проти генеруючого проксі


82

Просто цікаво, за яких обставин ви б віддали перевагу генерації проксі-сервісу із служби WCF, коли ви можете просто викликати дзвінки за допомогою ChannelFactory?

Таким чином вам не доведеться створювати проксі-сервер і турбуватися про регенерацію проксі-сервера, коли сервер оновлюється?

Дякую


Завжди використовуйте ChannelFactory. Я не можу стверджувати цього досить рішуче.
Том Редферн,

Відповіді:


88

Існує 3 основних способи створення клієнта WCF:

  1. Нехай Visual Studio генерує ваш проксі. Це автоматично генерує код, який підключається до служби, читаючи WSDL. Якщо послуга зміниться з будь-якої причини, вам доведеться її відновити. Великою перевагою цього є те, що його легко налаштувати - у VS є майстер, і все це автоматично. Недоліком є ​​те, що ви покладаєтесь на VS, щоб виконувати всю важку роботу за вас, і тому ви втрачаєте контроль.

  2. Використовуйте ChannelFactoryз відомим інтерфейсом. Це покладається на те, що у вас є локальні інтерфейси, що описують послугу (контракт на обслуговування). Велика перевага полягає в тому, що набагато легше управляти змінами - вам все одно доведеться перекомпілювати та виправити зміни, але тепер ви не регенеруєте код, а посилаєтесь на нові інтерфейси. Зазвичай це використовується, коли ви керуєте як сервером, так і клієнтом, оскільки над ними можна набагато легше знущатись для модульного тестування. Однак інтерфейси можна писати для будь-якої служби, навіть для REST - подивіться на цей Twitter API .

  3. Напишіть власний проксі - це досить легко зробити, особливо для REST-послуг, використовуючи HttpClientабо WebClient. Це дає вам найкращий контроль зерна, але ціною багатьох службових API є рядки. Наприклад: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content;- якщо деталі API змінюються, ви не зіткнетеся з помилкою до часу виконання.

Особисто мені ніколи не подобався варіант 1 - покладатися на автоматично згенерований код безладно і втрачає надто великий контроль. Плюс це часто створює проблеми із серіалізацією - я закінчую двома однаковими класами (один у коді сервера, один автоматично згенерований), які можна ввести в порядок, але це біль.

Варіант 2 повинен бути ідеальним, але канали є занадто обмежуючими - наприклад, вони повністю втрачають вміст помилок HTTP . Тим не менш, мати інтерфейси, що описують послугу, набагато легше кодувати та підтримувати.


4
@MurHaf Nope - ця відповідь є повністю моєю власною роботою. Я ЗАВЖДИ приписую внески інших. Цю відповідь я написав на основі років роботи з сервісами SOAP у .Net на різних робочих місцях. Ця стаття, на яку ви посилаєтесь, починається з березня 2013 року, тоді як моя відповідь була написана у квітні 2010 року - за 3 роки до цього! Якщо стався плагіат, він скопіював мене. Вам слід перевірити дати, перш ніж висувати звинувачення, оскільки це дуже легко зробити.
Кіт,

@MurHaf ми навіть не приходимо до однакових висновків - ця стаття рекомендує автоматично генерувати проксі (варіант 1) як "простий". Я описую це як просте налаштування, але безладне та біль у підтримці. Він навіть не обговорює написання власного проксі (варіант 3).
Кіт

1
Думаю, слід також згадати SvcUtil, оскільки це один із найпоширеніших способів "написати" клієнта.
Mare Infinitus

21

Я використовую ChannelFactory разом із методом MetadataResolver.Resolve. Клієнтська конфігурація заважає, тому я отримую ServiceEndpoint з сервера.

Коли ви використовуєте ChannelFactory (Of T), T - це або оригінальний контракт, який ви можете отримати за допомогою посилання у вашому проекті, або згенерований екземпляр контракту. У деяких проектах я згенерував код із посилання на сервіс, оскільки не зміг додати посилання на DLL контракту. Ви навіть можете створити асинхронний контракт із посиланням на службу і використовувати цей інтерфейс контракту з ChannelFactory.

Основним пунктом використання ChannelFactory для мене було позбавлення інформації про конфігурацію клієнта WCF. У прикладі коду нижче ви можете побачити, як досягти клієнта WCF без конфігурації.

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

У моєму остаточному проекті наявні прив'язки перевіряються на використання net.tcp або net.pipe, якщо такі є. Таким чином, я можу використовувати найкраще з наявних прив’язок для своїх потреб. Я покладаюся лише на той факт, що кінцева точка метаданих існує на сервері.

Сподіваюся, це допоможе

До речі, це робиться за допомогою .NET 3.5. Однак він працює і з 4.0.


Чудові речі. Я використовую MetadataResolver.Resolve також для конфігурації, але я не думав про вирішення прив'язки з сервера. Дуже хороший момент!
Sleeper Smith

голос за згадуванняThe main point of using ChannelFactory to get rid of the WCF client config
Курубаран

11

Для того, щоб скористатися ChannelFactory<T>цією послугою, ви повинні бути готові поділитися договірними зборами між службою та клієнтом. Якщо з вами це нормально, ви ChannelFactory<T>можете заощадити час.


@Charles - ти можеш пояснити, чому це неправда?
Aran Mulholland

6
@Aran: Я думаю, що те, що хоче сказати Ендрю, є правильним - якщо ви не хочете генерувати факсиміле класів контрактів, то вам потрібно мати доступ до оригіналів. Це правда, що так чи інакше вам потрібно мати ці контрактні класи. Ви можете їх генерувати, писати від руки або отримати вихідний код послуги (якщо мова цієї мови). Спільний доступ до збірок - це найпростіший спосіб, але це не завжди можливо. (Можливо, я просто сприймаю Ендрю занадто буквально, але тут важлива ясність.)
Ігбі Ларгеман

2
@Charles добре, отже, ви говорите, що можете використовувати ChannelFactory <T>, навіть якщо у вас не було доступу до збірок, вручну кодуючи інтерфейс T, а потім використовуючи це.
Aran Mulholland

1
@Aran: так, або шляхом ручного кодування, або за допомогою такого інструменту, як svcutil (за умови, що служба запущена і доступна).
Ігбі Ларгеман

9

Проксі створюватиме функції асинхронізації, що дуже приємно.


2
так - одночасно, як "Додати посилання на послугу" Visual Studio, так і svcutil.exe у командному рядку забивають вашу конфігурацію до невпізнання .... принаймні за допомогою svcutil.exe ви можете визначити перемикач "/ noconfig" .....
marc_s

1
ChannelFactory також надає асинхронні методи: msdn.microsoft.com/en-us/library/ms731177.aspx Але я вважаю за краще використовувати шаблон T4 для створення асинхронного класу за допомогою ThreadPool, який буде викликати синхронні методи.
SandRock,

1
В якості оновлення: .NET 4.5 ChannelFactory <T> також підтримує асинхронні функції на основі завдань.
gimpf

8

Моя відповідь - це своєрідний підсумок відповідей Кіта та Ендрю Зайця .

Якщо ви не керуєте сервером, але маєте лише WSDL / URL-адресу, генеруйте проксі-сервер за допомогою Visual Studio або svcutil. (Зверніть увагу, що Visual Studio іноді не спрацьовує, коли svcutil працює краще).

Коли ви керуєте сервером і клієнтом, надайте спільний доступ до інтерфейсів / контрактів і зателефонуйте ChannelFactory
.


2

Справа не лише в економії часу. Використання згенерованого проксі-сервера WSDL небезпечно, оскільки якщо ви забудете оновити посилання на службу, ви можете залишити рішення у несумісному стані. Все компілюється, але контракт на обслуговування порушений. Я категорично пропоную використовувати ChannelFactory, коли це можливо, ви значно полегшуєте своє життя.

Можливою альтернативою може бути написання сценарію попередньої збірки, який викликає утиліту SVCUtil для створення проксі-сервера щоразу, коли ви будуєте свій проект, але в будь-якому випадку ChannelFactory набагато охайніший та елегантніший.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.