我想要实现的非常简单:我有一个Windows窗体(.NET 3.5)应用程序,它使用一个路径来读取信息.用户可以使用我提供的选项表单修改此路径.
现在,我想将路径值保存到文件中供以后使用.这将是保存到此文件的众多设置之一.该文件将直接位于应用程序文件夹中.
我理解有三种选择:
ConfigurationSettings文件(appname.exe.config)
注册处
自定义XML文件
我读到.NET配置文件没有预见到将值保存回来.至于注册表,我想尽可能远离它.
这是否意味着我应该使用自定义XML文件来保存配置设置?如果是这样,我希望看到代码示例(C#).
我已经看过关于这个问题的其他讨论,但我仍然不清楚.
如果您使用Visual Studio,那么很容易获得可持久的设置.在Solution Explorer中右键单击项目,选择Properties.选择"设置"选项卡,如果设置不存在,请单击超链接.使用"设置"选项卡创建应用程序设置.Visual Studio创建文件Settings.settings
并Settings.Designer.settings
包含Settings
从ApplicationSettingsBase继承 的单例类.您可以从代码中访问此类以读取/写入应用程序设置:
Properties.Settings.Default["SomeProperty"] = "Some Value"; Properties.Settings.Default.Save(); // Saves settings in application configuration file
此技术适用于控制台,Windows窗体和其他项目类型.
请注意,您需要设置设置的范围属性.如果选择应用程序范围,则Settings.Default.
如果您计划保存到与可执行文件相同的目录中的文件,这是一个使用JSON格式的好解决方案:
using System; using System.IO; using System.Web.Script.Serialization; namespace MiscConsole { class Program { static void Main(string[] args) { MySettings settings = MySettings.Load(); Console.WriteLine("Current value of 'myInteger': " + settings.myInteger); Console.WriteLine("Incrementing 'myInteger'..."); settings.myInteger++; Console.WriteLine("Saving settings..."); settings.Save(); Console.WriteLine("Done."); Console.ReadKey(); } class MySettings : AppSettings{ public string myString = "Hello World"; public int myInteger = 1; } } public class AppSettings where T : new() { private const string DEFAULT_FILENAME = "settings.json"; public void Save(string fileName = DEFAULT_FILENAME) { File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this)); } public static void Save(T pSettings, string fileName = DEFAULT_FILENAME) { File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings)); } public static T Load(string fileName = DEFAULT_FILENAME) { T t = new T(); if(File.Exists(fileName)) t = (new JavaScriptSerializer()).Deserialize (File.ReadAllText(fileName)); return t; } } }
注册表是禁止的.您不确定使用您的应用程序的用户是否有足够的权限写入注册表.
您可以使用该app.config
文件来保存应用程序级设置(对于使用您的应用程序的每个用户都是相同的).
我会将用户特定的设置存储在XML文件中,该文件将保存在Isolated Storage或SpecialFolder.ApplicationData目录中.
接下来,从.NET 2.0开始,可以将值存储回app.config
文件.
本ApplicationSettings
类不支持设置保存到app.config文件.这非常依赖于设计,使用正确安全的用户帐户(想想Vista UAC)运行的应用程序没有对程序安装文件夹的写入权限.
您可以与ConfigurationManager
班级对抗系统.但是,简单的解决方法是进入"设置"设计器并将设置的范围更改为"用户".如果这会导致困难(例如,设置与每个用户相关),则应将"选项"功能放在单独的程序中,以便可以请求权限提升提示.或放弃使用设置.
我想分享一个我为此而建的图书馆.这是一个很小的库,但对.settings文件有很大改进(恕我直言).
该库名为Jot(GitHub),这是我写的关于它的旧代码项目文章.
以下是您如何使用它来跟踪窗口的大小和位置:
public MainWindow() { InitializeComponent(); _stateTracker.Configure(this) .IdentifyAs("MyMainWindow") .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState)) .RegisterPersistTrigger(nameof(Closed)) .Apply(); }
与.settings文件相比的好处:代码要少得多,而且容易出错,因为你只需要提一次每个属性.
使用设置文件,您需要提及五次每个属性:一次是在显式创建属性时,另外四次是在代码中来回复制值.
存储,序列化等是完全可配置的.当目标对象由IOC容器创建时,您可以[挂钩] []以便它自动将跟踪应用于它所解析的所有对象,这样您需要做的就是使属性持久化是一个[Trackable]属性在上面.
它是高度可配置的,您可以配置: - 数据持久化并应用于全局或每个跟踪对象 - 如何序列化 - 存储位置(例如文件,数据库,在线,隔离存储,注册表) - 可以取消应用/持久化的规则财产的数据
相信我,图书馆是一流的!
registry/configurationSettings/XML参数似乎仍然非常活跃.随着技术的进步,我已经全部使用了它们,但我最喜欢的是基于Threed的系统与隔离存储相结合.
以下示例允许将名为properties的对象存储到隔离存储中的文件中.如:
AppSettings.Save(myobject, "Prop1,Prop2", "myFile.jsn");
可以使用以下方法恢复属性
AppSettings.Load(myobject, "myFile.jsn");
这只是一个样本,不是最佳实践的暗示.
internal static class AppSettings { internal static void Save(object src, string targ, string fileName) { Dictionaryitems = new Dictionary (); Type type = src.GetType(); string[] paramList = targ.Split(new char[] { ',' }); foreach (string paramName in paramList) items.Add(paramName, type.GetProperty(paramName.Trim()).GetValue(src, null)); try { // GetUserStoreForApplication doesn't work - can't identify. // application unless published by ClickOnce or Silverlight IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly(); using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Create, storage)) using (StreamWriter writer = new StreamWriter(stream)) { writer.Write((new JavaScriptSerializer()).Serialize(items)); } } catch (Exception) { } // If fails - just don't use preferences } internal static void Load(object tar, string fileName) { Dictionary items = new Dictionary (); Type type = tar.GetType(); try { // GetUserStoreForApplication doesn't work - can't identify // application unless published by ClickOnce or Silverlight IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly(); using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storage)) using (StreamReader reader = new StreamReader(stream)) { items = (new JavaScriptSerializer()).Deserialize >(reader.ReadToEnd()); } } catch (Exception) { return; } // If fails - just don't use preferences. foreach (KeyValuePair obj in items) { try { tar.GetType().GetProperty(obj.Key).SetValue(tar, obj.Value, null); } catch (Exception) { } } } }
一种简单的方法是使用配置数据对象,将其保存为XML文件,并在本地文件夹中使用应用程序的名称,并在启动时将其读回.
以下是存储表单位置和大小的示例.
配置数据对象是强类型的并且易于使用:
[Serializable()] public class CConfigDO { private System.Drawing.Point m_oStartPos; private System.Drawing.Size m_oStartSize; public System.Drawing.Point StartPos { get { return m_oStartPos; } set { m_oStartPos = value; } } public System.Drawing.Size StartSize { get { return m_oStartSize; } set { m_oStartSize = value; } } }
用于保存和加载的经理类:
public class CConfigMng { private string m_sConfigFileName = System.IO.Path.GetFileNameWithoutExtension(System.Windows.Forms.Application.ExecutablePath) + ".xml"; private CConfigDO m_oConfig = new CConfigDO(); public CConfigDO Config { get { return m_oConfig; } set { m_oConfig = value; } } // Load configuration file public void LoadConfig() { if (System.IO.File.Exists(m_sConfigFileName)) { System.IO.StreamReader srReader = System.IO.File.OpenText(m_sConfigFileName); Type tType = m_oConfig.GetType(); System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType); object oData = xsSerializer.Deserialize(srReader); m_oConfig = (CConfigDO)oData; srReader.Close(); } } // Save configuration file public void SaveConfig() { System.IO.StreamWriter swWriter = System.IO.File.CreateText(m_sConfigFileName); Type tType = m_oConfig.GetType(); if (tType.IsSerializable) { System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType); xsSerializer.Serialize(swWriter, m_oConfig); swWriter.Close(); } } }
现在,您可以创建一个实例并在表单的加载和关闭事件中使用:
private CConfigMng oConfigMng = new CConfigMng(); private void Form1_Load(object sender, EventArgs e) { // Load configuration oConfigMng.LoadConfig(); if (oConfigMng.Config.StartPos.X != 0 || oConfigMng.Config.StartPos.Y != 0) { Location = oConfigMng.Config.StartPos; Size = oConfigMng.Config.StartSize; } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { // Save configuration oConfigMng.Config.StartPos = Location; oConfigMng.Config.StartSize = Size; oConfigMng.SaveConfig(); }
生成的XML文件也是可读的:
70 278 253 229
我不喜欢使用web.config
或提议的解决方案app.config
.尝试阅读自己的XML.看看XML设置文件 - 不再需要web.config.
除了使用自定义XML文件以外,我们还可以使用其他更友好的文件格式:JSON或YAML文件。
如果您使用.NET 4.0 dynamic,那么此库确实非常易于使用(序列化,反序列化,嵌套对象支持和按需排序输出顺序+将多个设置合并为一个)JsonConfig(用法等效于ApplicationSettingsBase)
对于.NET YAML配置库...我还没有找到一个像JsonConfig一样易于使用的库
您可以将设置文件存储在此处列出的多个特殊文件夹(针对所有用户和每个用户)Environment.SpecialFolder枚举和多个文件(默认只读,针对每个角色,针对每个用户等)
获取特殊文件夹路径的示例:C#获取%AppData%的路径
如果选择使用多个设置,则可以合并这些设置:例如,合并默认+ BasicUser + AdminUser的设置。您可以使用自己的规则:最后一个覆盖值,依此类推。