之所以写这一篇,是因为前一篇提到了性能问题,所以在这一篇文章里,主要围绕着性能来对ConfigCache这个程序集进行重构。
要重构的点:
1 实例创建过多,引起不必要的性能消耗
2 将配置信息从文件读到内存时,然后在读内容时,去比较最后修改时间与内存中存储的时间是否相同 ,如果不同则重新从文件中读到信息到内存
解决第一个问题,很容易想到单例模式,这在我文章中有对泛型单例的介绍,各位可以参考。
本例使用单例模式,创建配置信息实体对象,保存在使用这个对象时,只会被创建一次。
1 ///2 /// 配置信息生产工厂 3 /// 4 public class ConfigFactory : Singleton5 { 6 private ConfigFactory() 7 { 8 9 }10 #region 私有11 12 /// 13 /// 配置文件管理类14 /// 15 static ConfigFilesManager cfm;16 17 #endregion18 19 #region 公开的属性20 public T GetConfig() where T : IConfiger21 {22 string configFilePath = string.Empty;23 string filename = typeof(T).Name;24 25 HttpContext context = HttpContext.Current;26 string siteVirtrualPath = string.IsNullOrEmpty(ConfigurationManager.AppSettings["SiteVirtrualPath"]) ?27 "/" : ConfigurationManager.AppSettings["SiteVirtrualPath"];28 if (context != null)29 {30 configFilePath = context.Server.MapPath(string.Format("{0}/Configs/{1}.Config", siteVirtrualPath, filename));31 }32 else33 {34 configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Configs\{0}.Config", filename);35 }36 37 if (!File.Exists(configFilePath))38 {39 throw new Exception("发生错误: 网站" +40 new FileInfo("fileName").DirectoryName41 + "目录下没有正确的.Config文件");42 }43 44 cfm = new ConfigFilesManager(configFilePath, typeof(T));45 return (T)cfm.LoadConfig();46 }47 #endregion48 49 }
1 ///2 /// 泛型单例基类 3 /// 4 public abstract class Singletonwhere TEntity : class 5 { 6 private static readonly Lazy _instance 7 = new Lazy (() => 8 { 9 var ctors = typeof(TEntity).GetConstructors(10 BindingFlags.Instance11 | BindingFlags.NonPublic12 | BindingFlags.Public);13 if (ctors.Count() != 1)14 throw new InvalidOperationException(String.Format("Type {0} must have exactly one constructor.", typeof(TEntity)));15 var ctor = ctors.SingleOrDefault(c => c.GetParameters().Count() == 0 && c.IsPrivate);16 if (ctor == null)17 throw new InvalidOperationException(String.Format("The constructor for {0} must be private and take no parameters.", typeof(TEntity)));18 return (TEntity)ctor.Invoke(null);19 });20 21 public static TEntity Instance22 {23 get { return _instance.Value; }24 }25 }
第二个问题,在ConfigFilesManager中已经处理的很完美,它会将上次读取文件的时间记录下来,与本次时间进行对比,如果相同,则直接从内容中取配置信息实体,否则,从文件中读取最新版本。
1 #region 重设配置类实例 2 ///3 /// 重设配置类实例 4 /// 5 ///6 internal IConfiger LoadRealConfig() 7 { 8 lock (lockHelper) 9 {10 DateTime newfileChangeTime = File.GetLastWriteTime(this.fileName);11 if (!newfileChangeTime.Equals(this.fileChangeTime))12 {13 IconfigInfo = ConfigSerialize.DeserializeInfo(ConfigFilePath, this.configType);14 this.fileChangeTime = newfileChangeTime;15 }16 }17 return IconfigInfo as IConfiger;18 }19 #endregion
本例中实体持久化到文件中,在读取信息时,是从文件到内存的反序列化的过程,对于双方的载体,其实也有其它实现的方式,如果文件持久化也可以用数据库来实现,而内存缓存机制也可以用Cache缓存来实现,下一篇,我会着重介绍一个.net Cache的用法。