目录
介绍
代码很简单
例子
设置类型
存储位置
错误处理
保存类
加载一个类
结论
介绍在开发应用程序时,我厌倦了为我创建的每个设置添加线条,所以我认为必须有更好的方法来处理它们。这就是结果。
这段代码提供了使用类进行设置。要添加新设置,只需在类中创建一个新属性。设置存储在一个简单的类中,设置是该类中的一个属性。不需要额外的代码来确保它被保存或加载。保护程序将读取所有属性并将它们全部保存到文件中。加载器将创建类,从而设置默认设置。文件中存在的任何值都将应用于该类。最后,返回类以供软件使用。
代码很简单首先是设置存储空间和设置文件名。人们可以根据需要改变这一点。
接下来,为了保存,将读取所有属性并一一保存到文件中。
对于读取,读取文件,如果名称作为属性存在于settings类中,则将其应用于类。这也可以在settings类中的set { }中进行一些验证。
使用的类可以命名为任何名称,并且可以有多个文件和设置。此示例使用默认文件名settings.config,但可以使用任何文件名来创建更多文件。
例子下面是一个简单的settings类示例:
public class Settings
{
public int Setting1 { get; set; }
public bool Setting2 { get; set; }
public double Setting3 { get; set; } = 7.6;
public DateTime Setting4 { get; set; }
public string Setting5 { get; set; } = "test";
public List Setting6 { get; set; } = new List()
{ "test1", "test2" };
}
以及如何使用它:
var settings = (Settings)GetSettings("Settings"); // name of class, from above
settings.Setting1 = Settings.setting1 + 1; // change some settings
settings.Setting4 = DateTime.Now;
SaveSettings(settings); // save all properties of the class to file
如前所述,这将读取类的属性并应用它们。到目前为止,它已经实现了以下类型:string、boolean、int、double和Datetime字符串列表(List)。对于其他类型,代码会给出异常,但代码很容易扩展。
存储位置当前代码将使用本地应用程序文件夹,它将在其中创建一个具有执行(您的)应用程序名称的文件夹。
错误处理这个例子有基本的错误处理。如果需要,可以添加额外的错误处理。
保存类public void SaveSettings(object settings, string filename = "settings.config")
{
// create storage folder and file name
string storageFolder = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
Path.GetFileNameWithoutExtension(Application.ExecutablePath));
if (!Directory.Exists(storageFolder))
Directory.CreateDirectory(storageFolder);
if (!Directory.Exists(storageFolder))
throw new Exception($"Could not create folder {storageFolder}");
string settingsFileName = Path.Combine(storageFolder, filename);
// create file and process class, save properties one by one
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings()
{
Indent = true,
};
XmlWriter writer = XmlWriter.Create(settingsFileName, xmlWriterSettings);
using (writer)
{
writer.WriteStartElement("settings");
var classType = settings.GetType();
var props = classType.GetProperties();
for (int i = 0; i < props.Length; i++)
{
string fileSetting = char.ToLower(props[i].Name[0]) + props[i].Name.Substring(1);
if (props[i].PropertyType == typeof(string))
{
var sett = classType.GetProperty(props[i].Name).GetValue(settings);
if (sett != null)
{
string s = sett.ToString();
if (!string.IsNullOrEmpty(s))
writer.WriteElementString(fileSetting, s);
}
}
else if (props[i].PropertyType == typeof(int))
{
writer.WriteElementString(fileSetting,
classType.GetProperty(props[i].Name).GetValue(settings).ToString());
}
else if (props[i].PropertyType == typeof(double))
{
writer.WriteElementString(fileSetting,
classType.GetProperty(props[i].Name).GetValue(settings).ToString());
}
else if (props[i].PropertyType == typeof(DateTime))
{
var dt = (DateTime)(classType.GetProperty(props[i].Name).GetValue(settings));
writer.WriteElementString(fileSetting, dt.ToOADate().ToString());
}
else if (props[i].PropertyType == typeof(bool))
{
writer.WriteElementString(fileSetting,
classType.GetProperty(props[i].Name).GetValue(settings).ToString());
}
else if (props[i].PropertyType == typeof(List))
{
List values =
classType.GetProperty(props[i].Name).GetValue(settings) as List;
string val = string.Join(",", values.ToArray());
writer.WriteElementString(fileSetting, val);
}
else
throw new Exception($"Unknown setting type found: {props[0].PropertyType}");
}
writer.WriteEndElement();
writer.Flush();
}
}
这是读取文件并将属性应用到类并返回它的代码。请注意,某些部分会引发异常,但可以更改为简单地返回默认设置。另请注意,该类返回一个对象,因为不可能返回实际的类。因此,需要对类使用的结果进行类型转换。
例子:
var mySettings = (MySettingsClass)GetSettings("MySettingsClass"); // here, the class
// is used is named MySettingsClass
public object GetSettings(string settingsClassName, string filename = "settings.config")
{
// get class type and create default class
var settingsType = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
from t in assembly.GetTypes()
where t.Name == settingsClassName
select t).FirstOrDefault();
object settings = Activator.CreateInstance(settingsType);
// create storage folder and file name
string storageFolder = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
Path.GetFileNameWithoutExtension(Application.ExecutablePath));
if (!Directory.Exists(storageFolder))
Directory.CreateDirectory(storageFolder);
if (!Directory.Exists(storageFolder))
throw new Exception($"Could not create folder {storageFolder}");
string settingsFileName = Path.Combine(storageFolder, filename);
// recreate file if missing and return default settings
if (!File.Exists(settingsFileName))
{
SaveSettings(settings);
return settings;
}
// read and process file
XmlDocument settingsFile = new XmlDocument();
try
{
settingsFile.Load(settingsFileName);
}
catch (Exception ex)
{
throw ex;
// option to return default data
SaveSettings(settings);
return settings;
}
XmlNode settingsNode = null;
int n = 0;
while (n < settingsFile.ChildNodes.Count && settingsNode == null)
{
if (settingsFile.ChildNodes[n].Name.ToLower() == "settings")
settingsNode = settingsFile.ChildNodes[n];
n++;
}
if (settingsNode == null)
{
throw new Exception($"Settings section is not found
in settings file {settingsFileName}");
// option to return default data
return settings;
}
var classType = settings.GetType();
var props = classType.GetProperties();
foreach (XmlNode setting in settingsNode.ChildNodes)
{
if (setting.ParentNode.Name.ToLower() != "settings")
break;
if (setting.NodeType != XmlNodeType.Element)
continue;
var settingName = props.Where
(w => string.Compare(w.Name, setting.Name, true) == 0).ToList();
if (settingName.Count == 0)
continue;
if (string.IsNullOrEmpty(settingName[0].Name))
continue;
// parse setting as type defines
if (settingName[0].PropertyType == typeof(string))
classType.GetProperty(settingName[0].Name).SetValue(settings, setting.InnerText);
else if (settingName[0].PropertyType == typeof(int))
{
int val = 0;
if (int.TryParse(setting.InnerText, out val))
classType.GetProperty(settingName[0].Name).SetValue(settings, val);
}
else if (settingName[0].PropertyType == typeof(double))
{
double val = 0;
if (double.TryParse(setting.InnerText, out val))
classType.GetProperty(settingName[0].Name).SetValue(settings, val);
}
else if (settingName[0].PropertyType == typeof(DateTime))
{
double val = 0;
if (double.TryParse(setting.InnerText, out val))
classType.GetProperty(settingName[0].Name).SetValue
(settings, DateTime.FromOADate(val));
}
else if (settingName[0].PropertyType == typeof(bool))
{
bool val = (string.Compare("true",
setting.InnerText, true) == 0) || setting.InnerText == "1";
classType.GetProperty(settingName[0].Name).SetValue(settings, val);
}
else if (settingName[0].PropertyType == typeof(List))
{
string val = setting.InnerText.Trim();
if (string.IsNullOrEmpty(val))
{
classType.GetProperty(settingName[0].Name).SetValue
(settings, new List());
continue;
}
List values = val.Split(',').ToList();
classType.GetProperty(settingName[0].Name).SetValue(settings, values);
}
else
throw new Exception
($"Unknown setting type found: {settingName[0].PropertyType}");
}
return settings;
}
这只是使用类作为参数并处理类的属性的简单方法。它具有最常见的类型,但可以轻松扩展。此外,文件名和位置也很容易更改。
https://www.codeproject.com/Tips/5325914/Easy-Loading-and-Saving-of-Settings-Stored-as-a-Si