一、引子
你是否也遇到过这样的问题:项目很多配置都写到了App.Config或Web.Config的AppSettings内,每个人都加了几条,到最后囤积了大量的配置,分不清哪个是有用的、哪个是没用的了。(即便加了相关注释,也是乱的可以)
1 <appSettings>
2 <!--是否抛出异常-->
3 <add key="HasException" value="true" />
4 <add key="Mess**********_Enable" value="true" />
5 <add key="Mess**********_CorpCode" value="" />
6 <add key="Mess**********_Url" value="" />
7 <add key="Mess**********_Account" value="" />
8 <add key="Mess**********_AuthKey" value="" />
9 <add key="Mess**********_CGID" value="" />
10 <add key="Mess**********_MaxNumberPerHour" value="" />
11 <add key="Mess**********_Signature" value="" />
12 <add key="Mess**********__Enable" value="true" />
13 <add key="JPush**********Key" value="**********" />
14 <add key="JPush**********Secret" value="**********" />
15 <add key="Aud**********Hosts" value="127.0.0.1:1000" />
16 <!--true开启 false 关闭-->
17 <add key="Mess**********_Enable" value="true" />
18 <!--key-->
19 <add key="Baidu**********Key" value="**********" />
20 <add key="Baidu**********Secret" value="**********" />
21 <!--微信开发者 AppId,Secret和Token-->
22 <add key="AppId" value="**********" />
23 <add key="Secret" value="**********" />
24 <add key="Token" value="**********" />
25 <!--证书文件路径(退款用)-->
26 <add key="CertPath" value="E:\cert\apiclient_cert.pem" />
27 <!--App证书文件路径(退款用)-->
28 <add key="AppCertPath" value="E:\cert\**********.pfx" />
29 </appSettings>
那么问题来了,怎么解决呢?
二、方案
将同类、同项目、同模块的配置放到自定义配置节下,统一管理、读取,(可能并不是很好的解决方案,不喜勿喷)。如:
1 <configuration>
2 <configSections>
3 <!--自定义Section声明-->
4 <!--name:自定义节点名称-->
5 <!--type:读取配置信息类的命名空间,所在程序集-->
6 <section name="AssemblyInfo" type="Hetring.ConfigReader.SectionReader,Hetring.ConfigReader" requirePermission="false"></section>
7 </configSections>
8
9 <!--名称同声明的name-->
10 <AssemblyInfo>
11 <add key="Name" value="Hetring.ConfigReader" />
12 <add key="Version" value="1.0" />
13 <add key="Description" value="This is description." />
14 </AssemblyInfo>
15 </configuration>
三、代码
自定义配置节处理程序,需继承System.Configuration.IConfigurationSectionHandler接口,并实现object Create(object parent, object configContext, XmlNode section)方法:
1 public class SectionReader : IConfigurationSectionHandler
2 {
3 public object Create(object parent, object configContext, System.Xml.XmlNode section)
4 {
5 lock (typeof(SectionReader))
6 {
7 Hashtable sectionSetting = new Hashtable();//存放配置信息,也可用Dictionary<string,string>
8
9 foreach (XmlNode node in section.ChildNodes)
10 {
11 if (node.NodeType == XmlNodeType.Element && node.Name == "add")
12 {
13 var key = node.Attributes["key"].Value;
14 var value = node.Attributes["value"].Value;
15 sectionSetting.Add(key, value);//放入hashtable中
16 }
17 }
18
19 return sectionSetting;
20 }
21 }
22 }
读取配置节时,需要用到System.Configuration.ConfigurationManager.GetSection(SectionName)方法,获取到的是object类型对象,而我们定义的处理程序返回的是Hashtable,直接转换即可:
1 public class AssemblyInfoConfig
2 {
3 /// <summary>
4 /// Section名称
5 /// </summary>
6 private static string SectionName = "AssemblyInfo";
7
8 private static Hashtable _settings { get; set; }
9
10 protected static Hashtable SectionSettings
11 {
12 get
13 {
14 //当无配置时,ConfigurationManager.GetSection()会返回null,这里强制创建一个hashtable,防止空引用
15 if (_settings == null)
16 _settings = (ConfigurationManager.GetSection(SectionName) as Hashtable) ?? new Hashtable();
17
18 return _settings;
19 }
20 }
21
22 public static string Name
23 {
24 get
25 {
26 return ObjectToString(SectionSettings["Name"]);
27 }
28 }
29
30 public static string Version
31 {
32 get
33 {
34 return ObjectToString(SectionSettings["Version"]);
35 }
36 }
37
38 public static string Description
39 {
40 get
41 {
42 return ObjectToString(SectionSettings["Description"]);
43 }
44 }
45
46 #region 私有方法
47
48 /// <summary>
49 /// 将Object转换为非null字符串
50 /// </summary>
51 /// <param name="value">待转换Object</param>
52 /// <returns>不为空的字符串(value为null,返回空字符串)</returns>
53 private static string ObjectToString(object value)
54 {
55 if (value == null)
56 return string.Empty;
57
58 return value.ToString();
59 }
60
61 #endregion
62 }
四、调用
写了个控制台测试下:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Console.WriteLine("Name:" + AssemblyInfoConfig.Name);
6 Console.WriteLine("Version:" + AssemblyInfoConfig.Version);
7 Console.WriteLine("Description:" + AssemblyInfoConfig.Description);
8
9 Console.ReadKey();
10 }
11 }
输出结果:
Name:Hetring.ConfigReader
Version:1.0
Description:This is description.