废话不多说,先来看一个一个正常的WPF应用程系的配置是什么样的鬼
通常我们经常使用 的是ConnectionString (应用程系的数据库连接配置) 和 AppSettings(应用程系的配置)
特别注意的是:ConnectionString 默认已经有两个配制项(不知道这样的说法准确不准确) 见图
红色框中的很显然我没有在配置文件中配置过。
下面进入我要说的主题:
1.先看一下,我的配置文件的读取方法
/// <summary>
/// 获取置配的值,会有异常,有异常是返回null
/// </summary>
/// <param name="configName"></param>
/// <returns></returns>
public static string GetConfig(string configName)
{
try
{
return ConfigurationManager.AppSettings[configName];
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// set the config item's value,if not Exist Auto Create,last save to config file
/// </summary>
/// <param name="configName"></param>
/// <param name="value"></param>
public static void SetConfig(string configName, string value)
{
Configuration cf = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
bool exists = false;
foreach (string key in cf.AppSettings.Settings.AllKeys)
{
if (key == configName)
{
exists = true;
continue;
}
}
if (exists)
{
cf.AppSettings.Settings[configName].Value = value;
}
else
{
cf.AppSettings.Settings.Add(configName, value);
}
cf.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(AppSettingsSectionName);
// save config value to file
svaeConfigValueToFile(configName, value);
}
/// <summary>
/// 依据连接串名字connectionName返回数据连接字符串
/// </summary>
/// <param name="configName">依据连接串名字</param>
/// <returns></returns>
public static string GetConnectionConfig(string configName)
{
try
{
return ConfigurationManager.ConnectionStrings[configName].ConnectionString.ToString();
}
catch (Exception)
{
return null;
}
}
///<summary>
///更新连接字符串 如果没有则自动创建
///</summary>
///<param name="newName">连接字符串名称</param>
///<param name="newConString">连接字符串内容</param>
public static void SetConnectionConfig(string configName, string value)
{
bool isExists = false;
if (ConfigurationManager.ConnectionStrings[configName] != null)
{
isExists = true;
}
ConnectionStringSettings css = new ConnectionStringSettings(configName, value);
Configuration cf = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (isExists)
{
cf.ConnectionStrings.ConnectionStrings.Remove(configName);
}
cf.ConnectionStrings.ConnectionStrings.Add(css);
cf.Save();
ConfigurationManager.RefreshSection(ConnectionStringsSectionName);
svaeConfigValueToFile(configName, value, "connectionStrings");
}
动态的配置,在配置文件里,肉眼是看不到,只有程序能认识,并且在下一次启动时,又要重先来动态的配置一次。
下面提供个方法,让动态配置,直接在配置文件显示,下次启动不需要再配置。
/// <summary>
/// update config item's value and save it in configuation file
/// </summary>
/// <param name="configName"></param>
/// <param name="value"></param>
/// <param name="groupName">appSettings or connectionSettings </param>
public static void svaeConfigValueToFile(string configName, string value, string groupName = "appSettings")
{
string configFileName = "App.config";
string filePath = FileHelper.GetProjectRootPath() + "/" + configFileName;
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode group = doc.DocumentElement.SelectSingleNode(groupName);
if (group == null)
{
group = doc.CreateNode(XmlNodeType.Element, groupName, null);
group.AppendChild(createXmlNode(doc, configName, value, groupName));
doc.AppendChild(group);
}
bool isFind = false;
foreach (XmlNode item in group.ChildNodes)
{
if (groupName == "connectionStrings")
{
if (item.Attributes["name"].InnerText == configName)
{
item.Attributes["connectionString"].InnerText = value;
isFind = true;
continue;
}
}
else
{
if (item.Attributes["key"].InnerText == configName)
{
item.Attributes["value"].InnerText = value;
isFind = true;
continue;
}
}
}
if (isFind == false)
{
group.AppendChild(createXmlNode(doc, configName, value, groupName));
}
doc.Save(filePath);
}
private static XmlNode createXmlNode(XmlDocument doc, string configName, string value, string groupName)
{
string name = "key";
string valuetag = "value";
if (groupName == "connectionStrings")
{
name = "name";
value = "connectionString";
}
XmlNode node = doc.CreateElement("add") as XmlNode;
XmlAttribute att = doc.CreateAttribute(name);
att.InnerText = configName;
XmlAttribute val = doc.CreateAttribute(valuetag);
val.InnerText = value;
node.Attributes.Append(att);
node.Attributes.Append(val);
return node;
}
2.再来看一下,这些个方法使用
3.如何快速和准确的操作呢
我们知道配置项是字符串,IDE不会自动提示,而且我们很容易输错,经常性记不住有些什么样的配置项,我们想IDE自动提示来减少输入,和出错,帮助我们记忆,
我是这样做的,新建一个ConfigItemName 的枚举,其中的每一项和配置项对应。如图
这样就满足我们上面说的需求
4.如何我们还想在应用程系正试使用的环境中,我们也想看到动态配置。我们就要再用数据库来保存这些配置项,那什么时候保存到数据库,我建议是利用程序退出事件触发器,在程序退出前,把所有和配制项保存到数据中,利用数据库保存还有一个好处是我们切换电脑的时候,所有的配置可以快速迁移。
数据结构
代码
/// <summary>
/// save the config file's config Item to database
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Application_Exit(object sender, ExitEventArgs e)
{
ConnectionStringSettingsCollection conns = ConfigurationManager.ConnectionStrings;
DatabaseOPtionHelper helper=null;
for (int i = 0; i < conns.Count; i++)
{
Config config = new Config();
if (!conns[i].Name.Contains("Local")) {
if (!string.IsNullOrWhiteSpace(conns[i].ConnectionString.ToString())) {
config.clientId = ConfigurationHelper.GetConfig(ConfigItemName.clientId.ToString());
config.configName = conns[i].Name;
config.configValue = conns[i].ConnectionString;
config.syncTime = DateTimeHelper.ConvertDateTimeToInt(DateTime.Now);
if (helper == null) {
helper = new DatabaseOPtionHelper();
}
helper.insertOrUpdate(config);
}
}
}
NameValueCollection collection = ConfigurationManager.AppSettings;
string[] keys = collection.AllKeys;
foreach (string key in keys)
{
if (!string.IsNullOrWhiteSpace(collection[key])){
Config config = new Config();
config.clientId = ConfigurationHelper.GetConfig(ConfigItemName.clientId.ToString());
config.configName =key;
config.configValue = collection[key];
config.syncTime = DateTimeHelper.ConvertDateTimeToInt(DateTime.Now);
if (helper == null)
{
helper = new DatabaseOPtionHelper();
}
helper.insertOrUpdate(config);
}
}
}代码不是很完善,因为每一条数据都要去走一次数据库的操作流程,如果朋友们有时间,可以改进一下,尽量只走一次数据的操作流程就把所有数据保存。
如果有不当的地方请原谅和指出。