Как создать клиентский код для нескольких служб WCF с общими типами - PullRequest
11 голосов
/ 26 января 2010

У меня есть несколько служб WCF, которые совместно используют некоторые контракты данных, и мне нужно сгенерировать код на стороне клиента с помощью svcutil.exe. Я столкнулся с ошибками, используя два наиболее очевидных способа сделать это, и мне нужна помощь.

Но сначала, вот услуги:

[ServiceContract( Namespace = "http://www.me.com/services/" )]
public interface IFooService {
    [OperationContract]
    Response RunFoo( Request request );
}
[ServiceContract( Namespace = "http://www.me.com/services/" )]
public interface IBarService {
    [OperationContract]
    Response RunBar( Request request );
}

Ответ и запрос определены в отдельной сборке:

[DataContract( Namespace = "http://www.me.com/shared/" )]
public class Request {
    [DataMember]
    public int Input { get; set; }
}
[DataContract( Namespace = "http://www.me.com/shared/" )]
public class Response {
    [DataMember]
    public int Result { get; set; }
}

Сервисы реализованы каким-то тривиальным способом, скомпилированы, опубликованы - давайте теперь перейдем на сторону клиента.

Включение обеих служб в командной строке svcutil, например:

svcutil /o:Client.cs http://hostname.com/FooService.svc http://hostname.com/BarService.svc

приведет к многочисленным сообщениям об ошибках о дублированных типах данных, начиная с

Ошибка: произошла ошибка проверки схемы, сгенерированной во время экспорта: Источник: Строка: 1 Колонка: 9087 Ошибка проверки: глобальный элемент 'http://schemas.microsoft.com/2003/10/Serialization/:anyType' уже объявлен.

и заканчивается

Ошибка: произошла ошибка проверки схемы, сгенерированной во время экспорта: Источник: Строка: 1 Колонка: 12817 Ошибка проверки: комплексный тип 'http://www.me.com/shared/:Response' уже объявлен.

Генерация файла на стороне клиента отдельно для каждой службы позволяет избежать этих ошибок:

svcutil /o:Foo.cs http://hostname.com/FooService.svc
svcutil /o:Bar.cs http://hostname.com/BarService.svc

Но тогда определения общих типов (таких как Request и Response) будут продублированы в Foo.cs, а затем в Bar.cs, что, очевидно, приведет к ошибкам компилятора.

Итак, каков обычный способ генерации кода на стороне клиента, потребляющего такие услуги ?

Ограничения:

  • не может отправить сборку, содержащую общие типы, клиенту (чтобы они могли использовать параметр / r svcutil.exe)
  • не может использовать команду «Добавить ссылку на службу ...» в Visual Studio - требуется командная строка svcutil (или другой инструмент командной строки).

Ответы [ 5 ]

5 голосов
/ 26 января 2010

Ну, в принципе, вы можете

  • либо поместите ваши общие типы в отдельную сборку, которую клиенты могут использовать при создании клиентского кода (который вы уже отклонили как невозможный)

или затем:

  • вы должны сгенерировать каждый прокси для сервисов отдельно, и каждый сервис получит свою собственную «копию» классов «Запрос» и «Ответ»

Либо вы можете поделиться общей сборкой - либо вы не можете - другого выбора, на самом деле, я не вижу.

4 голосов
/ 26 января 2010

Поскольку у вас есть правила для общей сборки DTO (почему, кстати?), Самый простой вариант в этом случае выглядит как , чтобы генерировать типы в разных пространствах имен C # (т.е. два вызова svcutil ), и сопоставьте данные между ними. По сути: относитесь к DTO из двух служб по совпадению.

Вы можете использовать такие вещи, как automapper, чтобы уменьшить объем работы, или вы можете просто сериализовать из типа A и десериализовать в тип B (при условии, что фактические data пространства имен и т. Д. Идентичны).

2 голосов
/ 05 августа 2010

WSCF Blue может приблизить вас к решению, если вы его еще не нашли.

http://wscfblue.codeplex.com/

Может создавать отдельные файлы для каждого типа, перезаписывая при последующих операциях.

0 голосов
/ 28 февраля 2013

Пожалуйста, скачайте WSCFblue-v1-Walkthrough zip по ссылке ниже, это может помочь вам получить его.

http://wscfblue.codeplex.com/releases/view/48529

0 голосов
/ 26 января 2010

Когда вы запустите утилиту клиента один раз, вы получите файл XXXXService.cs и файл output.config.

Если вы наблюдаете класс XXXXService, у вас есть все в файле. Вы можете разделить их как отдельный файл IXXXService и XXXService и файл datacontracts.

Затем вы можете запустить утилиту для второго сервиса и добавить файл IXXXService1.cs и 1XXXService.cs и те же самые контракты данных, которые вы можете использовать для совместного использования этих 2.

Я не уверен, что это может ответить на ваш вопрос. У меня был пример , который может вам помочь. Вы можете увидеть еще несколько примеров здесь , связанных с некоторыми материалами MVC и WCF.

...