В любой книжке по шарпу рассказывают о том, что такое сериализация объектов. Напомню сериализация – это просто сохранение всех свойств объекта, например, на жесткий диск для последующей загрузки (десериализации) и использования в дальнейшем. Достаточно написать волшебное слово
перед описанием объекта, и его уже можно легко сохранить используя класс BinaryFormatter из System.Runtime.Serialization. Казалось бы все просто и чего еще можно хотеть… Рассмотрим ситуацию когда ваш объект изменяется в процессе написания новых версий программы. Вы добавите новое свойство и обнаружите, что чтение (десериализация) старых данных перестало работать, так как объект изменился. Можно управлять десериализацией вручную, однако это накладно.
Так вот, чтобы избавиться от этих проблем можно написать свой [де]сериализатор используя Reflection:
private static void WriteObject(object obj, StreamWriter writer)
{
Type t = obj.GetType();
PropertyInfo[] pi = t.GetProperties();
writer.WriteLine(Begin(t.Name));
//Store all props
foreach (PropertyInfo p in pi)
writer.WriteLine(FormXmlLine(p.Name, p.GetValue(obj, null).ToString()));
writer.WriteLine(End(t.Name));
}
private static string Begin(string name)
{
return “<“ + name + “>”;
}
private static string End(string name)
{
return “</” + name + “>”;
}
private static string FormXmlLine(string name, string value)
{
return ” <“ + name + “>” + value + “</” + name + “>”;
}
Метод просто записывает значения всех свойств объекта в формате XML. Его можно легко расширить для сохранения вложенных объектов и коллекций, добавив проверку типа свойства и видоизменив к рекуррентному виду. Хотя это не всегда нужно.
Прочитать сохраненный объект можно так:
//Lets read
public static void ReadObject(string filename, object Obj)
{
Type ObjType = Obj.GetType();
using (XmlReader reader = XmlReader.Create(filename))
{
while (reader.Read())
{
if (reader.IsStartElement())
{
if (reader.Name == ObjType.Name)
{
//Do nothing!
}
else
{
PropertyInfo[] pi = ObjType.GetProperties();
foreach (PropertyInfo p in pi)
if (p.Name == reader.Name)
{
reader.Read();
//Read the text content of the element.
if (p.PropertyType.Name == “String”)
p.SetValue(Obj, reader.ReadString(), null);
if (p.PropertyType.Name == “Int32”)
p.SetValue(Obj, reader.ReadContentAsInt(), null);
if (p.PropertyType.Name == “Int64”)
p.SetValue(Obj, reader.ReadContentAsInt(), null);
if (p.PropertyType.Name == “Long”)
p.SetValue(Obj, reader.ReadContentAsLong(), null);
}
}
}
}
}
}
Дополнив это дело нужными типами данных и проверкой ошибок, можно легко сохранять и читать объекты. Но, главное, теперь классы сохраняемых объектов можно видоизменять не заботясь о сериализации. Понятно, что формат XML можно заменить любым другим по вкусу и сохранять не на диск, а в базу данных.