Двоичный форматер и свойства с \ без полей поддержки

У меня есть следующий класс, сериализованный в файл с помощью BinaryFormatter:

[Serializable]
public class TestClass
{
    public String ItemTwo { get; set; }
    public String ItemOne { get; set; }
}

Используя этот код:

FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, new TestClass{ItemOne = "ItemOne", ItemTwo = "ItemTwo"});
fs.Close();

При десериализации с использованием этого кода:

FileStream fs = new FileStream("DataFile.dat", FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();
TestClass addresses = (TestClass)formatter.Deserialize(fs);
fs.Close();

Я все получаю нормально. Тем не менее, теперь мне нужно, чтобы у класса были некоторые вспомогательные поля, например:

[Serializable]
public class TestClass
{
    private string _itemTwo;
    private string _itemOne;

    public String ItemTwo
    {
        get { return _itemTwo; }
        set { _itemTwo = value; }
    }

    public String ItemOne
    {
        get { return _itemOne; }
        set { _itemOne = value; }
    }
}

Моя проблема в том, что теперь по какой-то причине десериализация из предыдущей версии больше не работает. Я получил класс, но свойства остались пустыми.
Я не могу повлиять на процесс сериализации или прежнее состояние класса.
Как я могу получить файл для десериализации в текущий класс?

1 ответ

Решение

Если вы попытаетесь сериализовать первую версию TestClass задние поля будут автоматически сериализованы двоичным форматером. Авто свойства являются только синтаксическим сахаром, компилятор преобразует их в обычные свойства с полями поддержки. Например, если вы декомпилируете свое исходное консольное приложение (или библиотеку классов) с помощью ILSpy, вы увидите, что ваши личные поля объявлены как:

.field private string '<ItemOne>k__BackingField'

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

.field private string _itemOne

Подход будет объявить ISerializable интерфейс на вашем TestClass и получить значение исходных свойств, используя информацию, содержащуюся в классе SerializationInfo

[Serializable]
public class TestClass : ISerializable
{
    private string _itemTwo;
    private string _itemOne;

    public String ItemTwo
    {
        get { return _itemTwo; }
        set { _itemTwo = value; }
    }

    public String ItemOne
    {
        get { return _itemOne; }
        set { _itemOne = value; }
    }

    protected TestClass(SerializationInfo info, StreamingContext context)
    {
        _itemTwo = info.GetString("<ItemTwo>k__BackingField");
        _itemOne = info.GetString("<ItemOne>k__BackingField");
    }

    [SecurityPermissionAttribute(SecurityAction.Demand,
    SerializationFormatter = true)]
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        //Add data to your serialization process here
    }
}

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

Другие вопросы по тегам