Добавление ссылок на службы к нескольким службам WCF с общими классами

Я пытаюсь разделить свои веб-службы WCF на несколько служб вместо одной гигантской. Но Visual Studio (клиент Silverlight) дублирует общие классы, общие для обеих служб. Вот простой пример, иллюстрирующий мою проблему.

В этом примере есть две службы. Оба возвращают тип «Человек». По умолчанию VS создаст два отдельных прокси-сервера Person под уникальными пространствами имен. Это означает, что «Человек», возвращаемый различными службами, не может использоваться клиентом как одно и то же. Как я могу это исправить? Можно ли без написания прокси-классов самому?

Общий

[DataContract]
public class Person
{
    [DataMember]
    string FirstName { get; set; }
    [DataMember]
    string LastName { get; set; }
    [DataMember]
    string PrivateData { get; set; }
}

StaffService.svc

[ServiceContract(Namespace = "")]
public class StaffService
{
     [OperationContract]
     public Person GetPerson ()
     {
         return new Person {"John", "Doe", "secret"};
     };
}

PublicService.svc

[ServiceContract(Namespace = "")]
public class PublicService
{
     [OperationContract]
     public Person GetPerson ()
     {
         return new Person {"John", "Doe", "*****"};
     };
}

Спасибо за помощь! Джастин


person Justin    schedule 20.05.2009    source источник


Ответы (3)


В разделе «Дополнительно» раздела «Добавить ссылку на службу» есть флажок «Типы повторного использования в сборках, на которые имеются ссылки». Это будет искать типы, используемые в вашей службе, и если они уже существуют в ссылочной сборке, они будут использоваться, а не сгенерированный прокси-класс.

Одно предостережение заключается в том, что поиск выполняется только по «ссылочным сборкам», поэтому он не будет принимать прокси, созданные другими службами (и я считаю, что другое пространство имен также остановит его).

Обычно в моем проекте Silverlight есть бизнес-проект или проект домена, поэтому я добавляю в этот проект свои общие классы (обычно с помощью «Добавить существующий элемент»> «Добавить как ссылку», чтобы предоставить общий доступ к коду).

Как только это будет сделано, вы можете сгенерировать ссылки на свои сервисы, и они должны подобрать ваши существующие типы.

Надеюсь это поможет

person Nigel Sampson    schedule 20.05.2009
comment
Спасибо, Найджел. Я видел флажок «Повторное использование типов в ссылочных сборках» в диалоговом окне «Дополнительно». Вроде по умолчанию включен. Вы правы, что прокси, созданные другими службами, похоже, не принимаются. Когда вы говорите о добавлении собственных общих классов, я предполагаю, что они взяты из библиотеки классов Silverlight? Похоже, вы сами создаете прокси и передаете его службам. Это правильно? - person Justin; 21.05.2009
comment
Я поделился DataContracts между клиентом и сервером, я делаю это, добавляя существующий элемент, трюк заключается в том, чтобы убедиться, что вы выбрали добавить как ссылку, это означает, что класс разделяется между ними. По сути, я все еще создаю прокси службы (StaffServiceClient), но не классы (Person). - person Nigel Sampson; 21.05.2009
comment
Потрясающий Найджел. Я пошел вперед с этим решением и его работами. Немного поигрался, я вижу, что вы ДОЛЖНЫ заполнить атрибуты пространства имен в своих DataContracts, иначе по какой-то причине классы не будут выбраны. Также очень раздражает то, что мне приходится создавать отдельную сборку только для прокси на стороне клиента. Было бы намного лучше, если бы я мог просто связать источник с тем же проектом, в котором я создаю сервис. Причина в том, что я уже помещал сервис в отдельный проект, чтобы его можно было использовать в других проектах. - person Justin; 23.05.2009

Если вы сгенерируете прокси одновременно с помощью svcutil.exe, он сгенерирует только один тип. Я не знаю, как это сделать, добавив в проект ссылку на сервис.

Мы запускаем его в пакетном файле, поэтому я вырезал его и изменил имена, чтобы защитить невиновных. На самом деле речь идет о сопоставлении пространств имен служб вместе, а затем объединении всех URL-адресов. Он также имеет набор типов коллекции (для списков) и включает ссылку на сборку (на которую ссылаются некоторые другие ответы.

@ECHO OFF

SET cmd=C:\"Program Files"\"Microsoft SDKs"\Windows\v6.0a\bin\SvcUtil.exe
SET cmd=%cmd% /out:Traffic.cs /noConfig /collectionType:System.Collections.Generic.List`1

SET cmd=%cmd% /reference:..\..\..\lib\Architecture.Frameworks.dll

REM ######### Service namespace mappings (Service Contracts and Message Contracts)
SET cmd=%cmd% /namespace:"http://services.test.com/app/2005/09/"
SET cmd=%cmd%,"app.ServiceProxies"

REM ######### Schema namespace mappings (Data Contracts)
SET cmd=%cmd% /namespace:"http://schemas.company.com/app/2005/09/"
SET cmd=%cmd%,"Co.ServiceProxies.app.DataContracts"

REM ######### Set all the URLs that have common types
SET cmd=%cmd% http://localhost/Services/MyService1.svc
SET cmd=%cmd% http://localhost/Services/MyService2.svc

%cmd%

PAUSE

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

person Brian ONeil    schedule 20.05.2009
comment
Спасибо, Брайан. У вас есть пример или ссылка, чтобы объяснить, как это сделать? А пока я начну искать его сам. - person Justin; 20.05.2009
comment
Брайан, спасибо за ответ. В итоге я использовал другое решение, но в ближайшем будущем я увидел, что это очень полезно. - person Justin; 23.05.2009

svcutil.exe может повторно использовать типы из указанных сборок. Вы можете настроить это, установив свойства ссылки на службу или ключ / reference, если вы запускаете svcutil.exe вручную.

Если вы являетесь владельцем упомянутых служб, рассмотрите возможность помещения типов данных, таких как класс Person, в отдельную сборку, доступную как для клиента, так и для службы.

person Ihar Voitka    schedule 20.05.2009
comment
Вы также можете сделать это с помощью дополнительных настроек в диалоговом окне добавления ссылки на службу. - person Brian ONeil; 21.05.2009