Как создать клиентский код для нескольких служб WCF с общими типами
У меня есть несколько служб 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 Ошибка проверки: уже объявлен complexType '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 and Response) будут дублироваться в Foo.cs, а затем в Bar.cs, что приведет, очевидно, к ошибкам компилятора.
Итак, , что является обычным способом создания клиентского кода, использующего такие службы?
Ограничения:
- не может отправить клиенту сборку, содержащую общие типы (чтобы они могли использовать параметр svcutil.exe/r)
- не может использовать команду "Добавить ссылку на службу..." в Visual Studio - нужна командная строка svcutil (или другой инструмент командной строки).
Ответы
Ответ 1
Ну, в основном вы можете
- либо поместить ваши общие типы в отдельную сборку, которую клиенты могут использовать при генерации кода клиента (который вы уже уволили как невозможно)
а затем:
- вам нужно генерировать каждый прокси-сервер для служб отдельно, и каждая служба получит свою собственную "копию" классов "Запрос" и "Ответ"
Либо вы можете делиться общей сборкой, либо не может. На самом деле я не вижу другого выбора.
Ответ 2
Поскольку у вас есть правила для общей сборки DTO (почему, btw?), самым простым вариантом в этом случае является генерация типов в разных пространствах имен С# (т.е. два вызова на svcutil
) и отображение данных между двумя. По существу: относиться к DTO от двух сервисов как к совпадению.
Вы можете использовать такие вещи, как automapper, чтобы уменьшить работу, или вы можете вырезать сериализацию из типа A и десериализовать в тип B (при условии, что фактические пространства имен и т.д. идентичны).
Ответ 3
WSCF Blue может приблизиться к решению, если вы еще не нашли его.
http://wscfblue.codeplex.com/
Он может создавать отдельные файлы для каждого типа, перезаписывая последующие операции.
Ответ 4
Когда вы запустите клиентскую утилиту, как только вы получите файл XXXXService.cs и файл output.config.
Если вы соблюдаете класс XXXXService, у вас есть все в файле. Вы можете разделить их как отдельный файл IXXXService и XXXService и файл datacontracts.
Затем вы можете запустить утилиту для второй службы и добавить файлы IXXXService1.cs и 1XXXService.cs и те же данные, которые вы можете использовать для совместного использования для этих 2.
Я не уверен, может ли это ответить на ваш вопрос. Я использовал пример, который может вам помочь.
Вы можете увидеть еще несколько примеров здесь, связанных с некоторыми материалами MVC и WCF.
Ответ 5
Загрузите WSCFblue-v1-Walkthrough zip из приведенной ниже ссылки, это может помочь вам в этом.
http://wscfblue.codeplex.com/releases/view/48529