Пространство имен справочной службы WCF отличается от исходного - PullRequest
12 голосов
/ 29 июля 2009

У меня проблема с пространствами имен, используемыми ссылками на мои сервисы. У меня есть несколько служб WCF, скажем, с пространством имен MyCompany.Services.MyProduct ( фактические пространства имен длиннее ).
В рамках этого продукта я также предоставляю пример веб-сайта на C # .NET. Это веб-приложение использует пространство имен MyCompany.MyProduct.

Во время первоначальной разработки, сервис был добавлен в качестве ссылки на сайт проекта и используется напрямую. Я использовал фабричный шаблон, который возвращает экземпляр объекта, который реализует MyCompany.Services.MyProduct.IMyService. Пока все хорошо.

Теперь я хочу изменить это, чтобы использовать реальную справочную службу. После добавления ссылки и ввода MyCompany.Services.MyProduct в текстовое поле пространства имен он создает классы в пространстве имен MyCompany.MyProduct.MyCompany.Services.MyProduct . ПЛОХО! Я не хочу менять директивы using в нескольких местах только потому, что я использую прокси-класс. Поэтому я попытался добавить пространство имен к global::, но это не принято.

Обратите внимание, что я даже еще не удалил исходные ссылки на сборки, и "повторное использование типов" включено, но повторное использование, по-видимому, не было выполнено. Однако я не хочу хранить ссылки на сборки на моем образце веб-сайта, чтобы он все равно работал .

Единственное решение, которое я до сих пор придумал, - установить для пространства имен по умолчанию для моего веб-приложения значение MyCompany (поскольку оно не может быть пустым) и добавить ссылку на службу как Services.MyProduct. Предположим, что клиент хочет использовать мой пример веб-сайта в качестве отправной точки, и они изменяют пространство имен по умолчанию на OtherCompany.Whatever, это, очевидно, сломает мой обходной путь.

Есть ли хорошее решение этой проблемы?

Подводя итог : я хочу создать ссылочный прокси-сервер службы в исходном пространстве имен без ссылки на сборку.

Примечание: я видел этот вопрос , но не было найдено решения, приемлемого для моего варианта использования.


Редактировать. Как предположил Джон Сондерс, я отправил Microsoft свой отзыв об этом:
Элемент обратной связи @ Microsoft Connect

Ответы [ 3 ]

21 голосов
/ 29 июля 2009

Я добавил описание этого решения в свой блог. Та же самая информация на самом деле, но, возможно, чуть менее фрагментированная

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

Вы должны явно указать uri пространства имен в ваших ServiceContract и DataContracts ( см. Ниже для комментария ).

[ServiceContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public interface IService
{
    [OperationContract]
    CompositeType GetData();
}

[DataContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public class CompositeType
{
    // Whatever
}

Пространство имен может быть любым, но технически оно должно быть действительным URI, поэтому я выбрал эту схему. Возможно, вам придется собрать вручную, чтобы потом все работало, так что сделайте это.

После этого включите параметр Показать все файлы в обозревателе решений. Разверните ссылку на услугу, которую вы добавили ранее. Дважды щелкните файл Reference.svcmap.

Там будет элемент <NamespaceMappings />, который вам нужно будет отредактировать. Продолжая мой пример:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="http://company.com/MyCompany.Services.MyProduct"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

Сохраните файл, щелкните правой кнопкой мыши справку службы и выберите Обновить справку службы .

Вы можете добавить столько сопоставлений, сколько вам нужно (мне фактически понадобилось два). Эффект такой же, как у подхода svcutil /namespace:, но без использования самого утилиты командной строки, что упрощает обновление.

Разница с svcutil

Недостатком этого подхода является то, что вам необходимо использовать явные сопоставления пространства имен. Используя svcutil, у вас есть возможность отобразить все, что не отображено явно, как это (решение, на которое ссылался Джон Сондерс):

svcutil /namespace:*,MyCompany.Services.MyProduct ...

Вы можете подумать, что используете:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="*"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

но это будет не работать, потому что Visual Studio уже неявно добавляет это отображение, указывая на сгенерированное имя пространства имен, от которого мы пытаемся избавиться. Приведенная выше конфигурация приведет к тому, что Visual Studio будет жаловаться на дубликат ключа.

Пространства имен с явными объявлениями :
Если в вашем коде не указано пространство имен explit, кажется , что .NET сгенерирует uri вида http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct. Вы можете отобразить это так же, как и явные пространства имен в моем примере, но я не знаю, есть ли какая-либо гарантия для такого поведения. Поэтому лучше использовать явное пространство имен.

Примечание: сопоставление двух пространств TargetNamespace с одним и тем же пространством ClrNamespace, по-видимому, нарушает генерацию кода

1 голос
/ 29 июля 2009

Ваш вариант использования был неправильным.

Вы никогда не должны были включать сервис в качестве ссылки.

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

0 голосов
/ 29 октября 2013

В VS2010 и более поздних версиях есть способ настроить пользовательские пространства имен. В обозревателе решений выберите «Показать все файлы», затем откройте «Веб-ссылки» в дереве решения, выберите службу, выберите узел Reference.map, отобразите свойства и установите свойство пространства имен пользовательского инструмента.

К сожалению, у меня недостаточно репутации, чтобы показать скриншот.

...