Как поддерживать DataContractSerializer и XMLSerializer для одного контракта на одном хосте? - PullRequest
5 голосов
/ 11 июня 2010

В нашей производственной среде наши сервисы WCF сериализуются с помощью XMLSerializer.Для этого наши сервисные интерфейсы имеют атрибут [XMLSerializerFormat].Теперь нам нужно перейти на DataContractSerializer, но мы должны оставаться совместимыми с нашими существующими клиентами.Следовательно, мы должны предоставлять каждый сервис обоим сериализаторам.

У нас есть одно ограничение: мы не хотим переопределять каждый интерфейс контракта дважды, у нас есть 50 контрактных интерфейсов служб, и мы не хотим иметь

IIncidentServiceXml 
IIncidentServiceDCS
IEmployeeServiceXml 
IEmployeeServiceDCS
IContractServiceXml 
IContractServiceDCS

Как мы можем это сделать?


Дополнительная информация

Это описание того, что мы пробовали до сих пор, но яЯ хочу попробовать совершенно разные подходы:

Мы пытались создать все конечные точки с помощью кода в нашем собственном классе ServiceHostFactory.В основном мы создаем каждую конечную точку дважды.Проблема заключается в том, что во время выполнения WCF жалуется, что у службы есть две конечные точки с одинаковым именем контакта, но с разными экземплярами ContractDescription.В сообщении говорится, что мы должны использовать разные имена контрактов или повторно использовать один и тот же экземпляр ContractDescription.

Другая попытка:

Мы также пытались сделать это, используя разные пространства имен для каждого экземпляра ContractDescription.Таким образом, мы сохраним тот же интерфейс контракта (IIncidentService), но с двумя разными пространствами имен:

http://ourcompany/XML/IIncidentService
http://ourcompany/DCS/IIncidentService

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

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.XmlSerializerOperationBehavior
contract: http://ourcompany.cs/XML:IUserServiceWCF ----> System.NullReferenceException: Object reference not set to an instance of an object.
   at System.ServiceModel.Description.XmlSerializerMessageContractExporter.ExportFaults(Object state)
   at System.ServiceModel.Description.MessageContractExporter.ExportMessageContract()
   at System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext contractContext)
   at System.ServiceModel.Description.WsdlExporter.CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension)

Ответы [ 3 ]

1 голос
/ 14 июня 2010

Просто создайте свой объект, используя теги [DataContract] и [DataMember]. XmlSerializer и DataContractSerializer отлично сериализуют объект. Они обновили XmlSerializer в фреймворке 3.0 для обработки сериализации данных. DataContractSerializer может обрабатывать [Serializable] объекты, но поведение не является точным и требует некоторой настройки.

Просто создайте все свои объекты, используя контракты данных. Таким образом, вам не нужно беспокоиться о двух вызовах (по одному для каждого). Вы можете без проблем использовать XmlSerializer или DataContractSerializer.

Если вам нужно добавить атрибуты поведения, вы всегда можете добавить [Serializable] и [DataContract], если хотите.

[Serializable]
[DataContract]
public class Customer

{
    [DataMember]
    public int Age { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public int Number { get; set; }

    [DataMember]
    public string FullName { get; set; }

    [XmlIgnore]
    public int IgnoredNumber { get; set; }
}

XmlSerializer Сериализуется как:

<?xml version="1.0" encoding="utf-16" ?> 
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Age>88</Age> 
  <Name>Bob</Name> 
  <Number>808</Number> 
  <FullName>Bob Jones</FullName> 
  </Customer>

DataContractSerializer Сериализуется как:

  <?xml version="1.0" encoding="utf-8" ?> 
<Customer xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1">
  <Age>88</Age> 
  <FullName>Bob Jones</FullName> 
  <Name>Bob</Name> 
  <Number>808</Number> 
  </Customer>

Очевидно, что вы можете принудительно задать пространство имен, чтобы они оба точно совпали. Это только для примера.

1 голос
/ 12 июня 2010

Короткий ответ: вы не можете, по той же причине, что и в вашем сообщении об ошибке, вы не можете иметь слишком конечные точки с тем же именем, что вы фактически пытаетесь сделать. Я думаю, вам придется делать именно то, что вы говорите, что не хотите.

Это может быть единственным вариантом

Проблема в том, что указать служба заключается в использовании XmlSerializer вам нужно объявить [XmlSerializerFormat] атрибут на услуга или договор. Ну так как мы хотим использовать то же самое для обоих конечные точки мы не можем разместить там, так мы остались с размещением его на контракт. Тем не менее, когда он сводится к этому обе конечные точки используют тот же сервис и в то же время в то же время правильно контракт?

Ну, это не обязательно так. Вы может иметь контракт, вытекающий из контракт B, затем имейте обслуживание выполнить контракт А так, чтобы все в обоих контрактах является частью службы. Для этого примера тем не менее, контракт B будет нашим стандартный контракт, и контракт будет быть интерфейсом, который просто определяет Атрибут [XmlSerializerFormat].

Но я не могу обещать вам, что будет работать с вашим существующим клиентским кодом без изменений.

0 голосов
/ 12 июня 2010

Как насчет двух служб, реализующих один и тот же контракт?

Например:

class DcsService : Service
{}

[XmlSerializerFormat] 
class XmlService : Service
{}

class Service : IServiceContract
{}

Никогда не работал с XmlSerializer, но мы использовали эту конструкцию для других целей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...