Как я могу переопределить десериализацию в C # - PullRequest
5 голосов
/ 14 августа 2010

У меня есть класс, который с течением времени претерпит определенные изменения версии.Данные из этого класса сериализуются и десериализуются как часть запуска моего приложения.У меня проблема, если я обновляю класс, добавляя дополнительные свойства, а затем запускаю приложение, старые данные не загружаются должным образом.
Что я хочу сделать, так это переопределить этап десериализации, я нене забудьте вручную восстановить объект из xml, поскольку у меня хранится номер версии, и я могу использовать его для рекурсивного обновления версий объекта.

Есть ли интерфейс, который я могу реализовать, или атрибут, который я могу установить где-тобыть в состоянии сделать это?

Если вы не можете придумать способ сделать то, что я хочу, есть ли альтернативы?например, значения по умолчанию для свойств, которые могут отсутствовать в загружаемой версии XML.

Ответы [ 4 ]

5 голосов
/ 14 августа 2010

Реализация интерфейса IXmlSerializable .

2 голосов
/ 14 августа 2010

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

Также обратите внимание на интерфейс IDeserializationCallback.OnDeserialization, который позволяет настроить десериализацию.

1 голос
/ 14 августа 2010

Если речь идет именно о xml-сериализации, вам следует реализовать интерфейс IXmlSerializable. Если это двоичная сериализация, вы можете просто пометить новых членов атрибутом OptionalField.

Вы можете прочитать больше здесь: http://msdn.microsoft.com/en-us/library/ms229752(VS.80).aspx

0 голосов
/ 14 августа 2010

Вы можете реализовать интерфейс ISerializable и предоставить конструктор, который принимает объект SerializationInfo и StreamingContext , чтобы получить точное управление процессом сериализации / десериализации .

Например:

[Serializable]
public struct MyStruct: ISerializable
{
    private readonly int _x;
    private readonly int _y;

    // normal constructor
    public MyStruct(int x, int y) : this()
    {
        _x = x;
        _y = y;
    }

    // this constructor is used for deserialization
    public MyStruct(SerializationInfo info, StreamingContext text) : this()
    {
        _x = info.GetInt32("X");
        _y = info.GetInt32("Y");
    }

    public int X { get { return _x; } }
    public int Y { get { return _y; } }

    // this method is called during serialization
    [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("X", X);
        info.AddValue("Z", Y);
    }
}
...