используйте svcutil для сопоставления нескольких пространств имен для генерации прокси сервисов wcf

Я хочу использовать svcutil для сопоставления нескольких пространств имен wsdl с пространством имен clr при создании прокси служб. Я использую строгое управление версиями пространств имен, и, следовательно, сгенерированные пространства имен clr неудобны и могут означать, что многие изменения на стороне клиента будут изменены при изменении версии пространства имен wsdl / xsd. Пример кода будет лучше показать, что я хочу.

// Service code
namespace TestService.StoreService
{
    [DataContract(Namespace = "http://mydomain.com/xsd/Model/Store/2009/07/01")]
    public class Address
    {
        [DataMember(IsRequired = true, Order = 0)]
        public string street { get; set; }
    }

    [ServiceContract(Namespace = "http://mydomain.com/wsdl/StoreService-v1.0")]
    public interface IStoreService
    {
        [OperationContract]
        List<Customer> GetAllCustomersForStore(int storeId);

        [OperationContract]
        Address GetStoreAddress(int storeId);
    }

    public class StoreService : IStoreService
    {
        public List<Customer> GetAllCustomersForStore(int storeId)
        {
            throw new NotImplementedException();
        }

        public Address GetStoreAddress(int storeId)
        {
            throw new NotImplementedException();
        }
    }
}

namespace TestService.CustomerService
{
    [DataContract(Namespace = "http://mydomain.com/xsd/Model/Customer/2009/07/01")]
    public class Address
    {
        [DataMember(IsRequired = true, Order = 0)]
        public string city { get; set; }
    }

    [ServiceContract(Namespace = "http://mydomain.com/wsdl/CustomerService-v1.0")]
    public interface ICustomerService
    {
        [OperationContract]
        Customer GetCustomer(int customerId);

        [OperationContract]
        Address GetStoreAddress(int customerId);
    }

    public class CustomerService : ICustomerService
    {
        public Customer GetCustomer(int customerId)
        {
            throw new NotImplementedException();
        }

        public Address GetStoreAddress(int customerId)
        {
            throw new NotImplementedException();
        }
    }
}

namespace TestService.Shared
{
    [DataContract(Namespace = "http://mydomain.com/xsd/Model/Shared/2009/07/01")]
    public class Customer
    {
        [DataMember(IsRequired = true, Order = 0)]
        public int CustomerId { get; set; }
        [DataMember(IsRequired = true, Order = 1)]
        public string FirstName { get; set; }
    }
}

1. svcutil - without namespace mapping

svcutil.exe /t:metadata 
    TestSvcUtil\bin\debug\TestService.CustomerService.dll     
    TestSvcUtil\bin\debug\TestService.StoreService.dll

svcutil.exe /t:code *.wsdl *.xsd /o:TestClient\WebServiceProxy.cs

Сгенерированный прокси выглядит так

namespace mydomain.com.xsd.Model.Shared._2009._07._011
{
    public partial class Customer{}
}
namespace mydomain.com.xsd.Model.Customer._2009._07._011
{
    public partial class Address{}
}
namespace mydomain.com.xsd.Model.Store._2009._07._011
{
    public partial class Address{}
}

Клиентские классы находятся вне каких-либо пространств имен. Любое изменение в пространстве имен xsd подразумевает изменение всех операторов using в моем клиентском коде, и вся сборка будет нарушена.

2. svcutil - with wildcard namespace mapping

svcutil.exe /t:metadata 
    TestSvcUtil\bin\debug\TestService.CustomerService.dll 
    TestSvcUtil\bin\debug\TestService.StoreService.dll

svcutil.exe /t:code *.wsdl *.xsd /n:*,MyDomain.ServiceProxy 
    /o:TestClient\WebServicesProxy2.cs

Сгенерированный прокси выглядит так

namespace MyDomain.ServiceProxy
{
    public partial class Customer{}
    public partial class Address{}
    public partial class Address1{}
    public partial class CustomerServiceClient{}
    public partial class StoreServiceClient{}
}

Обратите внимание, что svcutil автоматически изменил один из классов Address на Address1. Мне это не нравится. Все клиентские классы также находятся в одном и том же пространстве имен.

What I want

Что-то вроде этого:

svcutil.exe 
    /t:code *.wsdl *.xsd 
    /n:"http://mydomain.com/xsd/Model/Shared/2009/07/01, MyDomain.Model.Shared;http://mydomain.com/xsd/Model/Customer/2009/07/01, MyDomain.Model.Customer;http://mydomain.com/wsdl/CustomerService-v1.0, MyDomain.CustomerServiceProxy;http://mydomain.com/xsd/Model/Store/2009/07/01, MyDomain.Model.Store;http://mydomain.com/wsdl/StoreService-v1.0, MyDomain.StoreServiceProxy" 
    /o:TestClient\WebServiceProxy3.cs

Таким образом, я могу логически сгруппировать пространство имен clr, и любое изменение пространства имен wsdl / xsd будет обрабатываться только при генерации прокси, не затрагивая остальную часть кода на стороне клиента.

Теперь это невозможно. Svcutil позволяет отображать только одно или все пространства имен, а не список отображений.

Я могу сделать одно отображение, как показано ниже, но не несколько

svcutil.exe 
    /t:code *.wsdl *.xsd 
    /n:"http://mydomain.com/xsd/Model/Store/2009/07/01, MyDomain.Model.Address" 
    /o:TestClient\WebServiceProxy4.cs

Но есть ли решение? Svcutil не волшебство, он написан на .Net и программно генерирует прокси. Кто-нибудь написал альтернативу svcutil или указал мне указания, чтобы я мог написать один.

 John Saunders09 июл. 2009 г., 20:21
Что произойдет, если вы просто воспользуетесь «Добавить ссылку на сервис»?
 softveda10 июл. 2009 г., 01:56
Я не пробовал, так как мне нужно использовать svcutil для генерации прокси из dll. Но я думаю, учитывая, что «добавить ссылку на службу» имеет возможность ввести только одно пространство имен, это будет то же самое, что и отображение пространства имен с подстановочными знаками.

Ответы на вопрос(2)

Решение Вопроса

предоставляя дополнительные параметры пространства имен, а не разделяя их точкой с запятой. Таким образом, ваш пример должен быть

svcutil.exe /t:code *.wsdl *.xsd 
/n:http://mydomain.com/xsd/Model/Shared/2009/07/01,MyDomain.Model.Shared 
/n:http://mydomain.com/xsd/Model/Customer/2009/07/01,MyDomain.Model.Customer
/n:http://mydomain.com/wsdl/CustomerService-v1.0,MyDomain.CustomerServiceProxy 
/n:http://mydomain.com/xsd/Model/Store/2009/07/01,MyDomain.Model.Store 
/n:http://mydomain.com/wsdl/StoreService-v1.0,MyDomain.StoreServiceProxy
/o:TestClient\WebServiceProxy3.cs

Хотя в настоящее время у меня возникают проблемы, когда типы, сгенерированные из файлов .xsd, не затрагиваются этими пространствами имен. Только типы, сгенерированные из файлов .wsdl. Документация подразумевает, что оба должны быть.

 Alexander19 мая 2016 г., 20:22
Я сталкиваюсь с этой проблемой только при использовании коммутатора / сериализатора: XmlSerializer. Для DataContractSerializer типы в основном включены в указанные пространства имен. Согласно этомуотве XmlSerializer не поддерживает эту функцию.
 Adi Lester12 февр. 2012 г., 15:39
Не повезло, что отображение пространства имен влияет и на типы xsd?
 Dave Cameron13 февр. 2012 г., 21:28
@ Lester: Я не стал заниматься этим дальше. Мы решили избежать необходимости использования xsds, внедрив эти типы в wsdls, как мне кажется. (Прошло 3 года, заметьте.) Может VS2010 улучшил эту ситуацию? Выше было сделано с VS2008.
 Ian Nelson15 окт. 2014 г., 16:46
@ DaveCameron Проходит еще пара лет, и я все еще решаю эту проблему в VS2013: -

если вы хотите отобразить все пространства имен схемы в одно пространство имен CLR, тогда:

SvcUtil "your wsdl file.xml" /n:*,RequiredClrNamespace

Ваш ответ на вопрос