Решил поделиться опытом :) Проблема сохранения настроек своего приложения - вечная и каждый ее решает по-своему. Я рассмотрю три разных способа ее решения. Естественно, что я не претендую на истину в последней инстанции, но возможно, данная информация окажется кому-нибудь полезной.
1. Сохранение настроек в собственный файл используя сериализацию.
Данный подход обладает достаточно большой гибкостью и удобен в использовании. Однако требует наибольшее количество кода.
Итак. Первое что нам понадобится - это класс с настройками. Для удобства использования, лучше всего если все члены класса будут статическими (Это, конечно, не самый лучший способ, однако, если наше приложение очень маленькое и не будет сильно расти/развиваться в дальнейшем, то можно и так. Более универсальный способ - это реализовать для класса с настройками паттерн singleton).
public class MySettings
{
public static int Setting1;
public static string Setting2;
}
Думаю - код класса понятен и проблем ни у кого не вызовет :)
Для сохранения данных - сериализуем:
XmlSerializer ser = new XmlSerializer(typeof(MySettings));
TextWriter writer = new StreamWriter("settings.xml");
ser.Serialize(writer, MySettings);
writer.Close();
Упс!.. Ошибка: "'MySettings' is a 'type' but is used like a 'variable' (CS0118)"
Переделываем:
MySettings settings=new MySettings();
XmlSerializer ser = new XmlSerializer(typeof(MySettings));
TextWriter writer = new StreamWriter("settings.xml");
ser.Serialize(writer, settings);
writer.Close();
Пожалуй стоит пояснить. Первой строкой мы создаем
объект класса MySettings, но поскольку он содержит
только статические члены - данные в переменных класса не изменятся, но мы получим объект (переменную), которую уже можно сериализовать :)
Компилируем, запускаем, смотрим что получилось:
<?xml version="1.0" encoding="utf-8"?>
<MySettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"/>
Упс!.. А где данные? Проблема в том, что
сериализовать статические члены класса нельзя! (В дополнение: xml-сериализация работает
только с public-членами класса). Делаем "финт ушами":
public class MySettings
{
public static int Setting1;
public static string Setting2;
public int _Setting1
{
get{ return Setting1;}
set{ Setting1=value;}
}
public string _Setting2
{
get{ return Setting2;}
set{ Setting2=value;}
}
}
Компилируем, запускаем, смотрим:
<?xml version="1.0" encoding="utf-8"?>
<MySettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<_Setting1>5</_Setting1>
<_Setting2>test</_Setting2>
</MySettings>
Вот оно! :) Суть в том, что через не-статические public-члены класса сериализатор получает доступ к статическим. :)
Ну а теперь - самое легкое: десериализация.
XmlSerializer deser = new XmlSerializer(typeof(MySettings));
TextReader reader = new StreamReader("settings.xml");
settings=((MySettings)ser.Deserialize(reader));
reader.Close();
2. "Ручное" сохранение в файл.
Поклонникам C++ рекомендуется :) В смысле - смотрите и завидуйте!
Итак. В .Net Framework в пространстве имен System.IO есть один замечательный класс - File, которым мы и воспользуемся. В частности, статическими функциями ReadAllLines и WriteAllLines.
Первое что на надо сделать для сохранения данных, это подготовить и заполнить массив строк:
string[] settings = new string[5];
settings[0] = "setting1=" + setting1.ToString();
settings[2] = "setting1=" + setting2.ToString();
Примечание: Многие увидевшие такой код наверняка захотят оторвать мне руки :)) Однако, сделано это специально, для того, чтобы показать, что делать если настройки сохранить надо, времени мало (лень), да и настроек 2-3 штуки. Естественно, что в серьезном приложении так делать нельзя!
После чего пишем
одну строку кода(!!!) и все:
File.WriteAllLines("settings.txt", settings);
При желании, можно указать и кодировку:
File.WriteAllLines("settings.txt", settings, Encoding.GetEncoding(1251));
Теперь перейдем к самому ответственному - чтению настроек. :)
string[] settings=File.ReadAllLines("settings.txt");
foreach(string s in settings)
{
string[] tmp=s.Split(new char[] {'='}, StringSplitOptions.RemoveEmptyEntries);
if(tmp.Length==2) //на всякий случай
{
switch(tmp[0])
{
case "setting1":
Int32.TryParse(tmp[1], out setting1); //тоже, чтобы не падало :)
break;
case "setting2":
setting2 = tmp[1];
break;
}
}
}
Вообщем-то и все.
3. Использование класса Settings.
Внимание: данный способ работает только в Visual Studio. По крайней мере в Sharp Delevop 2.2 этого точно нет. Более того: данный способ доступен только для WinForms или консольных проектов.
Первое что нам надо сделать - это добавить те настройки, что мы хотим сохранять. Делается это в разделе Properties списка файлов нашего проекта. Там дважды кликаем на раздел Settings и получаем в результате окно с таблицей. В этой таблице придумываем и вводим имена перменных (в которых и будут храниться наши настройки) их тип и значение по-умолчанию.
Доступ к настройкам осуществляется так:
Properties.Settings.Default.имя_нашей_перменной = значение;
После компиляции рядом .exe файлом будет лежать файл с таким же именем и расширением .exe.config. В этом файле хранятся
значения по-умолчанию для наших настроек. Об этом надо помнить! Сами же настройки приложения хранятся в
Documents and Settings\имя_пользователя\Local Settings\Application Data\имя_компании_из_AssemblyInfo.cs\имя_приложения.exe_StrongName_<разные левые числа>\номер_версии"
Причем номер версии берется в AssemblyInfo.cs из атрибута [assembly: AssemblyVersion("1.0.0.0")]
Если его изменить - то путь для настроек также изменится и, соответсвенно - наше приложение запустится с настройками по-умолчанию. (Тому, кто это придумал в Microsoft, по-хорошему следовало бы оторвать руки...)
К счастью - атрибут [assembly: AssemblyFileVersion("1.0.0.0")] можно менять как хочется :)
Самое веселое, что сохранять текущие настройки куда-либо помимо указанного пути стандартными средствами нельзя!
Настройки загружаются автоматически при старте программы. Сохранять их надо вручную, вот так:
Properties.Settings.Default.Save();
В случае, если вам надо сбросить все настройки в их значения по умолчанию, используется команда:
Properties.Settings.Default.Reset();
Ну и хватит наверное :) Более подробно - читаем МСДН.