2015-11-19 5 views
3

Не имея реальной предвидения, я сериализовал большой набор данных, украшенных только Serializable, используя NetDataContractSerializer, и теперь я хотел бы добавить новое поле. Какие у меня варианты?NetDataContractSerializer Deserialization With New Property

оригинальный класс выглядит примерно так (с несколькими уровнями наследования и довольно много полей):

[Serializable] 
public class InheritedClass : BaseClass 
{ 
    public string StringId { get; set; } 
} 

А теперь я хотел бы добавить еще одно свойство, что-то вроде:

[Serializable] 
public class InheritedClass : BaseClass 
{ 
    public string StringId { get; set; } 
    public int IntId { get; set; } 
} 

Теперь, когда я обновить класс и перейти к десериализации, я получаю исключение, так как новое поле нет, что-то вроде:

Exception thrown: 'System.Runtime.Serialization.SerializationException' in System.Runtime.Serialization.dll 

Additional information: Error in line 1 position 601. 'Element' '_x003C_StringId_x003E_k__BackingField' from namespace 'http://schemas.datacontract.org/2004/07/QT' is not expected. Expecting element '_x003C_IntId_x003E_k__BackingField'. 

Итак, это имеет смысл, так как NetDataContractSerializer требует того же класса. Я могу обойти, что с помощью приписывать DataMember как:

[DataMember(IsRequired = false)] 

Проблема то в том, что переход на DataMember (как я должен был сделать заранее, или использовать другой сериалайзер) изменяет неявное алфавитный порядок, а затем большинство мои поля беззвучно десериализуются, как известно.

Я попытался добавить заказ, встроенный с заказом на диск, вручную (через свойства Order атрибута), но, похоже, это тоже не соблюдается. (Я не вижу значения порядка, которые я мог бы сопоставить в необработанном xml.)

Есть ли другие возможности, помимо написания чего-либо, чтобы загрузить xml и вставить отсутствующий узел? (Или, что то же самое, настроить параллельный тип и десериализовать из одного повторного сериализации в другой?) Если нет, я, вероятно, просто загружу текущий тип и десериализую в JsonNet или protobuf, но я пропускаю что-то более простое с DataMember/и т.д?

ответ

1

Маркировка типа [Serializable] означает, что тип следует сериализовать сериализатором публичных и частных полей - не его свойств. При добавлении нового поля то, что обычно используется для обработки устаревших данных, заключается в том, чтобы пометить его [OptionalField], чтобы указать, что он не всегда будет присутствовать в потоках сериализации - но один не может сделать это с помощью автоматически реализованного свойства, поскольку один не может получить доступ к секретному полю поддержки.

Решение явно реализовать все новые свойства, и отметьте поле подкладочный с обязательным атрибутом:

[Serializable] 
public class InheritedClass : BaseClass 
{ 
    public string StringId { get; set; } 

    [OptionalField] 
    int intId; 

    public int IntId { get { return intId; } set { intId = value; } } 
}  
Смежные вопросы