刚刚学习C#,觉得它与Delphi真的很相似,毕竟是同一个老爸创造的东西,所以相似也是十分正常的。
今天学习了使用 ConfigurationManager,这玩意的作用就是管理应用程序的设置了。一般用法就是
setting1 = ConfigurationManager.AppSettings["setting1"].ToString();
setting2 = ConfigurationManager.AppSettings["setting2"].ToString();
......
可以对应读出app.config中的配置内容,大概就是:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="setting1" value="settingvalue1"/>
<add key="setting2" value="settingvalue2"/>
......
</appSettings>
</configuration>
这个类是个好东西,方便程序员读取本地设置。但因为它太方便了,所以我曾经见过一些教程的示范代码是随用随读取,即是哪个地方需要配置了,就马上用上面的代码读取。我觉得这是十分低效的做法,我喜欢把所有的配置都放到一个基本设置类里面去的,一次读出,这样有效地控制程序模块间的不统一性以及读取文件的延时,如这样:
class BaseAppValueConf
{
public static string setting1 = "";
public static string setting2 = "";
......
public static void initMe()
{
setting1 = ConfigurationManager.AppSettings["setting1"].ToString();
setting2 = ConfigurationManager.AppSettings["setting2"].ToString();
......
}
}
不知大家有没有这个感觉,写这种读取、写入配置的工作是一件低技术、重复、不好玩的事、而且费神费力的事。每写一个配置的名称就要重复写它的名字很多次(4次), 如果一个程序有个几十个设置,那就相当惹人烦,而且很容易错,所以我这样去做:
创建一个抽象的基类,把它放在一个公共的文件中,我自己就用 FlexAppSetting.cs,方便其它应用能共享:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Configuration;
namespace FlexAppSetting
{
public abstract class CustomBaseAppValueConf
{
private static bool hasKey(string[] ak, string n)
{
for (int i = 0; i < ak.Count(); i++)
{
if (ak[i] == n) return true;
}
return false;
}
abstract public void initMe();
protected void _initMe(CustomBaseAppValueConf cbavc)
{
Type selfType = cbavc.GetType();
System.Reflection.FieldInfo [] fis = selfType.GetFields();
for (int i = 0; i < fis.Count(); i++)
{
string[] ak = ConfigurationManager.AppSettings.AllKeys;
if (hasKey(ak, fis[i].Name))
{
if (fis[i].FieldType.Name == "Int32")
{
int v;
try
{
v = Convert.ToInt32(ConfigurationManager.AppSettings[fis[i].Name].ToString());
}
catch (Exception)
{
v = 0;
}
fis[i].SetValue(selfType, v);
}
else
{
fis[i].SetValue(selfType, ConfigurationManager.AppSettings[fis[i].Name].ToString());
}
}
}
}
}
}
然后在某个应用程序中,当要读取配置时,只要这样做就行了。
class BaseAppValueConf : CustomBaseAppValueConf
{
public static string setting1 = "";
public static string setting2 = "";
public static int nonSaveSetting = 2;
......
public static void initMe()
{
_initMe(this);
......
nonSaveSetting = 5555;
}
}
....
BaseAppValueConf bavc = new BaseAppValueConf();
BaseAppValueConf.appPath = System.AppDomain.CurrentDomain.BaseDirectory;
bavc.initMe();
这个CustomBaseAppValueConf 的作用就是对照着程序中的各设置值的名字,自动从app.config中读取出来,比原来要方便,而且不容易错,只要在程序中写一次变量名,在xml中再写一次就行了。
CustomBaseAppValueConf中用到了C#的反射机制,这是个好东西,与Delphi里的RTTI十分相似,但比Delphi的要强。
另外,希望各位前辈指正一下程序。总觉得 if (hasKey(ak, fis[i].Name)) 这句不应该这样写,但又没找到好的方法,所以就这样写了。