在面向服务中讲配置文件,肯定是要把它与具体领域分离,即它有普遍的一般性。在程序开发过程中,难免会用到一些易变性,全局的常量信息,我们通常的作法是把它们放在Web.config或者自定义的文件中,当然你的配置文件可以是XML,二进制的等等,但一般时候我们选择用XML标准的文件。
看全局配置项目的结构如下:
下面我来介绍一下每个文件的使用:
ConfigFactory它是一个配置文件的工厂类,作用当然就是“从配置文件中生产对象”了,呵呵。(这讲不考虑性能问题)
1 /// <summary> 2 /// 配置信息生产工厂 3 /// </summary> 4 public class ConfigFactory 5 { 6 #region 私有 7 8 /// <summary> 9 /// 配置文件管理类 10 /// </summary> 11 static ConfigFilesManager cfm; 12 13 #endregion 14 15 #region 公开的属性 16 public T GetConfig<T>() where T : IConfiger 17 { 18 string configFilePath = string.Empty; 19 string filename = typeof(T).Name; 20 21 HttpContext context = HttpContext.Current; 22 string siteVirtrualPath = string.IsNullOrEmpty(ConfigurationManager.AppSettings["SiteVirtrualPath"]) ? 23 "/" : ConfigurationManager.AppSettings["SiteVirtrualPath"]; 24 if (context != null) 25 { 26 configFilePath = context.Server.MapPath(string.Format("{0}/Configs/{1}.Config", siteVirtrualPath, filename)); 27 } 28 else 29 { 30 configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Configs\{0}.Config", filename); 31 } 32 33 if (!File.Exists(configFilePath)) 34 { 35 throw new Exception("发生错误: 网站" + 36 new FileInfo("fileName").DirectoryName 37 + "目录下没有正确的.Config文件"); 38 } 39 40 cfm = new ConfigFilesManager(configFilePath, typeof(T)); 41 return (T)cfm.LoadConfig(); 42 } 43 #endregion 44 45 }
ConfigFileManager它是一个对文件进行管理的类,它将配置文件反序列化成对象,并提供一段时间后,自动生成新版本的对象,为了线程安全,使用了lock
1 /// <summary> 2 /// 基本文件配置信息管理者 3 /// </summary> 4 internal class ConfigFilesManager 5 { 6 7 #region 私有 8 /// <summary> 9 /// 配置接口 10 /// </summary> 11 IConfiger configer; 12 /// <summary> 13 /// 锁对象 14 /// </summary> 15 object lockHelper = new object(); 16 17 /// <summary> 18 /// 配置文件修改时间 19 /// </summary> 20 DateTime fileChangeTime; 21 22 /// <summary> 23 /// 配置文件所在路径 24 /// </summary> 25 string fileName = null; 26 27 Type configType = null; 28 29 #endregion 30 31 #region 属性 32 33 /// <summary> 34 /// 当前配置类的实例 接口 35 /// </summary> 36 internal IConfiger IconfigInfo 37 { 38 get { return configer; } 39 set { configer = value; } 40 } 41 42 /// <summary> 43 /// 配置文件所在路径 44 /// </summary> 45 internal string ConfigFilePath 46 { 47 get { return fileName; } 48 49 } 50 51 #endregion 52 53 #region 构造 54 55 /// <summary> 56 /// 初始化文件修改时间和对象实例 57 /// </summary> 58 internal ConfigFilesManager(string fileName, Type type) 59 { 60 this.fileName = fileName; 61 //得到配置文件的 改时间 62 this.configType = type; 63 fileChangeTime = File.GetLastWriteTime(this.fileName); 64 this.configer = ConfigSerialize.DeserializeInfo(this.fileName, this.configType); 65 } 66 67 #endregion 68 69 #region 配置操作 70 71 #region 加载配置类 72 /// <summary> 73 /// 加载配置类 74 /// </summary> 75 /// <returns></returns> 76 internal IConfiger LoadConfig() 77 { 78 return IconfigInfo as IConfiger; 79 } 80 #endregion 81 82 #region 重设配置类实例 83 /// <summary> 84 /// 重设配置类实例 85 /// </summary> 86 /// <returns></returns> 87 internal IConfiger LoadRealConfig() 88 { 89 lock (lockHelper) 90 { 91 DateTime newfileChangeTime = File.GetLastWriteTime(this.fileName); 92 if (!newfileChangeTime.Equals(this.fileChangeTime)) 93 { 94 IconfigInfo = ConfigSerialize.DeserializeInfo(ConfigFilePath, this.configType); 95 this.fileChangeTime = newfileChangeTime; 96 } 97 } 98 return IconfigInfo as IConfiger; 99 } 100 #endregion 101 102 #region 保存配置 103 /// <summary> 104 /// 保存配置 105 /// </summary> 106 /// <returns></returns> 107 internal bool SaveConfig() 108 { 109 lock (lockHelper) 110 { 111 return ConfigSerialize.Serializer(ConfigFilePath, IconfigInfo); 112 } 113 } 114 #endregion 115 116 #endregion 117 118 }
ConfigSerialize它是一个配置文件序列化和反序列化的功能类,它返回的对象必须是继承自IConfiger接口的对象
1 /// <summary> 2 /// 配置序列化操作类 3 /// </summary> 4 internal class ConfigSerialize 5 { 6 #region 反序列化指定的类 7 8 /// <summary> 9 /// 反序列化指定的类 10 /// </summary> 11 /// <param name="configfilepath">config 文件的路径</param> 12 /// <param name="configtype">相应的类型</param> 13 /// <returns></returns> 14 public static IConfiger DeserializeInfo(string path, Type type) 15 { 16 17 IConfiger iconfiginfo; 18 FileStream fs = null; 19 try 20 { 21 fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 22 XmlSerializer serializer = new XmlSerializer(type); 23 iconfiginfo = (IConfiger)serializer.Deserialize(fs); 24 } 25 catch (Exception ex) 26 { 27 throw ex; 28 } 29 finally 30 { 31 if (fs != null) 32 { 33 fs.Close(); 34 } 35 } 36 37 return iconfiginfo; 38 } 39 40 41 42 #endregion 43 44 #region 保存(序列化)指定路径下的配置文件 45 46 /// <summary> 47 /// 保存(序列化)指定路径下的配置文件 48 /// </summary> 49 /// <param name="configFilePath">指定的配置文件所在的路径(包括文件名)</param> 50 /// <param name="configinfo">被保存(序列化)的对象</param> 51 /// <returns></returns> 52 public static bool Serializer(string path, IConfiger Iconfiginfo) 53 { 54 bool succeed = false; 55 FileStream fs = null; 56 XmlSerializer serializer = null; 57 try 58 { 59 fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); 60 serializer = new XmlSerializer(Iconfiginfo.GetType()); 61 serializer.Serialize(fs, Iconfiginfo); 62 //成功则将会返回true 63 succeed = true; 64 } 65 catch (Exception ex) 66 { 67 throw ex; 68 } 69 finally 70 { 71 if (fs != null) 72 { 73 fs.Close(); 74 serializer = null; 75 } 76 } 77 78 return succeed; 79 } 80 81 #endregion 82 83 }
IConfiger它是配置信息实体的统一接口,它提供了统一的配置信息操作返回类型,在读取具体配置信息时,只要类型强转换就可以了。
1 namespace ConfigCache 2 { 3 using System; 4 /// <summary> 5 /// 配置信息类接口 6 /// </summary> 7 public interface IConfiger { } 8 }
可能有些园友会问,那配置信息的实体呢及配置信息的文件呢?
我要告诉您的是,这些信息是与应用领域相关的,所以不在这个项目中呈现,它要应用到具体的领域项目中,就像这样:
在每一个领域解决方案的WEB项目中,都有一个Configs文件夹,我们的配置信息文件和实体都在这里显示,它们是成对出现的,如WebConfig.cs它是一个网站信息配置的实体,而对应的WebConfig.Config就是它对应的配置信息文件,它们的代码如下:
1 namespace TEstMv3.Config 2 { 3 public class WebConfig : IConfiger 4 { 5 public string PageSize { get; set; } 6 public string CategoryID { get; set; } 7 } 8 }
webconfig.config是一个XML标准的文件:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <WebConfig> 3 <PageSize>10</PageSize> 4 <CategoryID>2</CategoryID> 5 </WebConfig>
其中<WebConfig>是实体文件的类名,这个要注意一下。
调用用时,可以这样:
1 new ConfigCache.ConfigFactory().GetConfig<WebConfig>().PageSize;
好了,事实上现在我们就可以工作了,而对于怎么去提升配置文件读取的性能,我会另外写一篇文件的,介请收看。