Слушаю подкаст Радио-Т в прямом эфире, и пишу о кастомной сериализации объектов, в приложениях.
Как я делал давно-давно? Делал я просто, сохраняя текстовый файлик в виде ключ=значение по одному в строку. Работает это хорошо, но саппортить тяжело, легко ошибиться :(
Второй вариант, который я недавно использовал – сохранение ini файла через WinApi, который работает довольно быстро, делает правильные файлики, но все-же ошибиться и там можно :( Код класса:
public class IniWorker
{
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section,
string key,string def, StringBuilder retVal, int size, string filePath);
public string FilePath
{
get;
protected set;
}
public IniWorker(string Path)
{
this.FilePath = Path;
}
public void IniWriteValue(string Section, string Key, string Value)
{
WritePrivateProfileString(Section, Key, Value, this.FilePath);
}
public string IniReadValue(string Section, string Key)
{
StringBuilder temp = new StringBuilder(255);
GetPrivateProfileString(Section, Key, string.Empty, temp, 255, this.FilePath);
return temp.ToString();
}
public string IniReadValue(string Section, string Key, string DefaultValue)
{
StringBuilder temp = new StringBuilder(255);
GetPrivateProfileString(Section, Key, string.Empty, temp, 255, this.FilePath);
return string.IsNullOrEmpty(temp.ToString()) ? DefaultValue : temp.ToString();
}
public static void IniWriteValue(string Section, string Key, string Value, string FilePath)
{
WritePrivateProfileString(Section, Key, Value, FilePath);
}
public static string IniReadValue(string Section, string Key, string FilePath, string DefaultValue)
{
StringBuilder temp = new StringBuilder(255);
GetPrivateProfileString(Section, Key, string.Empty, temp, 255, FilePath);
return string.IsNullOrEmpty(temp.ToString()) ? DefaultValue : temp.ToString();
}
}
Примеры вызовов методов я приводить не буду – думаю и так понятно.
Третий вариант, который я применял на днях, отличается своей безопасностью в смысле того, что ошибиться довольно тяжело, однако он не слишком прост, хотя в моей случае он подходил хорошо: вариант этот использует рефлексию. Этот вариант я использовал даже с помощью атрибутов, чтобы задавать имена свойств. Пример кода, атрибут:
class OptionsAttribute: Attribute
{
public OptionsAttribute(string Name)
{
this.Name = Name;
}
public string Name { get; protected set; }
}
Сам класс использования сериализации, правда я делал вручную для малого количества свойств с парочкой типов:
class Options
{
public Options()
{
this. PingTimeOut = 256;
this.Load();
}
[OptionsAttribute("PingTimeOut")]
public int PingTimeOut { get; set; }
private void Load()
{
string path = Path.Combine(Application.StartupPath, "options.ini");
if (!File.Exists(path))
{
return;
}
string[] items = File.ReadAllLines(path, Encoding.UTF8);
PropertyInfo[] properties = typeof(Options).GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo property in properties)
{
OptionsAttribute attribute = property.GetCustomAttributes(typeof (OptionsAttribute), false).OfType<OptionsAttribute>().FirstOrDefault();
if (attribute == null)
{
continue;
}
for (int i = 0; i < items.Length; i++)
{
try
{
if (items[i].StartsWith(attribute.Name + "="))
{
string stringValue = items[i].Substring(attribute.Name.Length + 1);
object value = null;
if (property.PropertyType == typeof(int))
{
value = int.Parse(stringValue);
}
else if (property.PropertyType == typeof (bool))
{
value = bool.Parse(stringValue);
}
else
{
value = stringValue;
}
property.SetValue(this, value, null);
}
}
catch (Exception ex)
{
}
}
}
}
public void Save()
{
List<string> configuration = new List<string>();
PropertyInfo[] properties = typeof(Options).GetProperties(BindingFlags.Instance|BindingFlags.Public);
foreach (PropertyInfo property in properties)
{
OptionsAttribute attribute = property.GetCustomAttributes(typeof (OptionsAttribute), false).OfType<OptionsAttribute>().FirstOrDefault();
if (attribute == null)
{
continue;
}
configuration.Add(attribute.Name + "=" + property.GetValue(this, null).ToString());
}
File.WriteAllLines(Path.Combine(Application.StartupPath, "options.ini"), configuration.ToArray(), Encoding.UTF8);
}
}
Вот такие варианты для сериализации в простой текстовый файл. С сериализацией в XML ситуация другая, и она не для этого поста.
На этом все.

