XMLSerialization с несколькими пространствами имен - обратная совместимость - PullRequest
0 голосов
/ 20 февраля 2012

У меня есть версия 1.0 приложения с классом вроде:

class MyBaseDTO
{
   [XmlElementAttribute(DataType="base64Binary", IsNullable=true, ElementName="Data")]
   public byte[] Data{get;set}
}

и подкласс

class MySubDTO
{
    [XmlElementAttribute(DataType="base64Binary", IsNullable=true, ElementName="MoreData")]
    public byte[] MoreData{get;set}
}

теперь в версии 1.1 я хочу переместить MySubDTO.MoreData в MyBaseDTO. Проблема в том, что когда я общаюсь с сервером 1.0 с клиентом 1.1, MoreData никогда не сериализуется, потому что XML выглядит так:

<a:MyBaseDTO i:type="b:MySubDTO"><a:Data>...</a:Data><b:MoreData>...</b:MoreData></a:MyBaseDTO>

Если я добавлю

class MyBaseDTO
{
   [XmlElementAttribute(DataType="base64Binary", IsNullable=true, ElementName="Data")]
   public byte[] Data(){get;set}
   [XmlElementAttribute(DataType="base64Binary", IsNullable=true, ElementName="MoreData", NameSpace="MyBaseDTO")]
   public byte[] MoreData(){get;set}
}

Конечно, это работает, но я бы хотел, чтобы можно было понять, что MoreData может иметь два разных пространства имен. Я использую WCF для связи между веб-сервисами и использую DataContractSerializer для сериализации объектов на стороне сервера. Можно ли это сделать?

1 Ответ

0 голосов
/ 27 апреля 2012

У вас есть несколько вариантов:

  • Я думаю, что это тот сценарий, для которого был разработан IExtensibleDataObject (данные расширения)!Идея состоит в том, что если версия контракта v1 будет украшена интерфейсом данных расширения, он будет автоматически игнорировать, хранить и передавать данные из будущих версий контракта данных, включая будущие неизвестные типы, без каких-либо проблем.

Чтобы включить циклическое переключение для определенного типа, ваш тип должен использовать интерфейс IExtensibleDataObject.Интерфейс содержит одно свойство ExtensionData (возвращающее тип ExtensionDataObject).Свойство хранит любые данные из будущих версий контракта данных, которые неизвестны текущей версии.Вот пример того, что я имею в виду:

[DataContract]
public class Person : IExtensibleDataObject
{
    [DataMember]
    public string fullName;
    private ExtensionDataObject theData;

    public virtual ExtensionDataObject ExtensionData
    {
        get { return theData; }
        set { theData = value; }
    }
}

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

Вы всегда можете отключить эту функцию циклического отключения, либо установив ignoreExtensionDataObject в значение true в конструкторе DataContractSerializer, либоустановка для свойства IgnoreExtensionDataObject значения true в атрибуте ServiceBehaviorAttribute.У него есть снижение производительности, поэтому, если оно вам не нужно, я бы его отключил.

  • В приведенных выше инструкциях необходимо переключиться на DataContractSerializer.Если вы не можете сделать это для этого типа, вам, возможно, придется использовать IDataContractSurrogate для перевода этого типа XML в тип DataContract, который выглядит точно так же, как вы.также позволяет выполнять настраиваемую сериализацию и десериализацию JSON для каждого типа или объекта.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...