WCF ChannelFactory против создания прокси


82

Просто интересно, при каких обстоятельствах вы бы предпочли сгенерировать прокси из службы WCF, если вы можете просто вызывать вызовы с помощью ChannelFactory?

Таким образом, вам не придется создавать прокси и беспокоиться о его регенерации при обновлении сервера?

благодаря


Всегда используйте ChannelFactory. Я не могу сказать об этом достаточно четко.
Tom Redfern

Ответы:


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 Нет - это полностью моя собственная работа. Я ВСЕГДА приписываю вклад других. Я написал этот ответ, основываясь на годах работы с 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 без config.

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

В моем последнем проекте availableBindings проверяется на использование 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
Курубаран 03

11

Что ж, чтобы использовать, ChannelFactory<T>вы должны быть готовы делиться сборками контрактов между службой и клиентом. Если вас это устраивает, вы ChannelFactory<T>можете сэкономить время.


@ Чарльз, ты можешь объяснить, почему это неправда?
Аран Малхолланд

6
@Aran: Я думаю, что Эндрю правильно сказал, что если вы не хотите создавать факсимиле классов контрактов, вам понадобится доступ к оригиналам. Это правда, что так или иначе вам нужны эти контрактные классы. Вы можете сгенерировать их, написать вручную или получить исходный код сервиса (если он на том же языке). Совместное использование сборок - самый простой способ, но это не всегда возможно. (Может быть, я просто воспринимаю Эндрю слишком буквально, но здесь важна ясность.)
Игби Ларджман,

2
@Charles в порядке, вы говорите, что можете использовать ChannelFactory <T>, даже если у вас не было доступа к сборкам, вручную кодируя интерфейс T, а затем используя его.
Аран Малхолланд

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.