Blue Ghost
год назад
[AttributeUsage(AttributeTargets.Field)]
public class EnumDescriptionAttribute: Attribute
{
public readonly string description;
public EnumDescriptionAttribute(string description)
{
this.description = description;
}
}
public enum etest
{
[EnumNameAttribute("Значение 1")]
value1,
[EnumNameAttribute("Значение 2")]
value2,
…
}
Как видите – здесь все просто :)
((EnumDescriptionAttribute)typeof(etest).GetField(p.ToString()).GetCustomAttributes(typeof(EnumDescriptionAttribute), true)[0]).description;
public static string[] GetAllEnumDescription()
{
T[] vals=(T[])Enum.GetValues(typeof(T));
string[] names = new string[vals.Length];
for (int i = 0; i < vals.Length; i++)
names[i] = GetEnumDescription(vals[i]);
return names;
}
public static string GetEnumDescription(T p)
{
return ((EnumDescriptionAttribute)typeof(T).GetField(p.ToString()).GetCustomAttributes(typeof(EnumDescriptionAttribute), true)[0]).description;
}
Начнем с создания нового проекта. Будет это Windows Forms Application с одной формой (я покажу только как разработывается форма с настройками приложения):
MessageBox.Show(Properties.Settings.Default.setting1.ToString());
public string Setting3
{
get
{
return Properties.Settings.Default.setting3;
}
set
{
string tmp = value.ToLower();
Properties.Settings.Default.setting3 = tmp;
}
}
this.textBox1.DataBindings.Add("Text", this, "Setting3");
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();
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;
}
}
}
Вообщем-то и все.
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();
Ну и хватит наверное :) Более подробно - читаем МСДН.