Двоичный форматер и свойства с \ без полей поддержки
У меня есть следующий класс, сериализованный в файл с помощью 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
как вы хотите, чтобы ваши вспомогательные поля были инициализированы во время десериализации.