在面向服務中講配置文件,肯定是要把它與具體領域分離,即它有普遍的一般性。在程序開發過程中,難免會用到一些易變性,全局的常量信息,我們通常的作法是把它們放在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;
好了,事實上現在我們就可以工作了,而對於怎么去提升配置文件讀取的性能,我會另外寫一篇文件的,介請收看。