.net 序列化通用的方法

 1//是否写日志
  2#define txtLogAll
  3
  4using System;
  5using System.Web;
  6using System.Xml.Serialization;
  7using System.IO;
  8using System.Runtime.Serialization;
  9using System.Runtime.Serialization.Formatters.Soap;
 10using System.Runtime.Serialization.Formatters.Binary;
 11using System.Web.Caching;
 12using System.Threading;
 13using tjb.Utility.Caching;
 14using System.Xml;
 15using System.Text;
 16
 17
 18namespace tjb.Utility.Config
 19{
 20
 21    文件序列化的类型
 42
 43    /// <summary>
 44    /// 序列化基类  by Tjb 2007/06 
 45    /// T 类型不能创建多态的多个实例
 46    /// 优化和修正,增加配置文件备份 2008/9/18
 47    /// 修改:获取实例时加锁
 48    /// 修改:
 49    /// SaveAs(T Tobj, string FileFullName, bool BackupOnError) 方法增加线程锁定。防止多线程冲突 2008/10/24
 50    /// </summary>
 51    /// <typeparam name="T">T 必须有无参数的构造函数</typeparam>

 52    [Serializable]
 53    public abstract class IConfig<T> where T : IConfig<T>new()
 54    {
 55
 56        #region Exceptions
 57        private Exception __ConfigException;
 58        /// <summary>
 59        /// 读取或保存时发生的错误
 60        /// </summary>

 61        [XmlIgnore, SoapIgnore]
 62        public Exception Exception
 63        {
 64            get
 65            {
 66                return __ConfigException;
 67            }

 68            private set
 69            {
 70                if (value != null)
 71                {
 72                    HasError = true;
 73                    __ConfigException = value;
 74#if txtLogAll
 75                    Log.WriteLog(value);
 76#endif
 77                }

 78            }

 79        }

 80        private bool __HasError = false;
 81        /// <summary>
 82        /// 获取一个值 指示读取或者保存时是否发生错误
 83        /// 如果当前错误被获取后,此标志将被置为false
 84        /// </summary>

 85        [XmlIgnore, SoapIgnore]
 86        public bool HasError
 87        {
 88            get return __HasError; }
 89            private set { __HasError = value; }
 90        }

 91        #endregion

 92
 93        #region 序列化类型  可重写
 94
 95        private Formatter _CurrentFormatter = Formatter.Xml;
 96        /// <summary>
 97        /// 序列化的方式
 98        /// </summary>      

 99        [XmlIgnore]
100        protected virtual Formatter CurrentFormatter
101        {
102            get
103            {
104                return _CurrentFormatter;
105            }

106            set
107            {
108                _CurrentFormatter = value;
109            }

110        }

111
112        #endregion

113
114        #region 获取单个实例
115
116        /// <summary>
117        /// 获取Cache中缓存T的key
118        /// </summary>

119        public static string CacheKEY
120        {
121            get
122            {
123                // return typeof(T).GUID.ToString("N");
124                return typeof(T).FullName;
125            }

126        }

127        /// <summary>
128        /// 从缓存(缓存KEY为T的命空间加类名)获取当前类的实例,如果缓存不存在则读取文件(ConfigFileFullName), 并缓存。 
129        /// </summary>

130        public static T Instance
131        {
132            get
133            {
134                T c = CacheUtility.Get<T>(CacheKEY);
135                if (c == null)
136                {
137                    //这中方式无异于不加锁
138                    //object Monitor = new object();
139                    //lock (Monitor)
140                    lock (typeof(T))
141                    {
142                        c = CacheUtility.Get<T>(CacheKEY);
143                        if (c == null)
144                        {
145                            c = new T().Read();
146#if DEBUG
147                            CacheUtility.SetSlidingExpiration(CacheKEY, c, c.ConfigFileFullName, 7, CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(CallR));
148#else
149                            CacheUtility.SetSlidingExpiration(CacheKEY, c, c.ConfigFileFullName, 7, CacheItemPriority.NotRemovable, null);
150#endif
151                        }

152                    }

153                }

154                return c;
155            }

156        }

157
158        #endregion

159
160        #region Caching..
161
162        /// <summary>
163        /// 从ConfigFileName指定文件以CurrentSerializeType读取实例,如果存在缓存则移除并重新进行缓存
164        /// 如果不存在则以InitConfig初始化类,创建并保存文件
165        /// </summary>
166        /// <returns></returns>

167        protected T ResetCacheAndRead()
168        {
169            ResetCache();
170            return Read();
171        }

172        /// <summary>
173        /// 移除CacheKEY 缓存
174        /// </summary>

175        public void ResetCache()
176        {
177            HttpRuntime.Cache.Remove(CacheKEY);
178        }

179        #endregion

180
181        #region 获取
182
183        /// <summary>
184        /// 读取缓存中的实例如果不存在则
185        /// 从ConfigFileName指定文件以CurrentSerializeType读取实例
186        /// 如果不存在则以InitConfig初始化类,创建并保存文件
187        /// </summary>
188        /// <returns></returns>

189        virtual protected T Read()
190        {
191            return Read(ConfigFileFullName, true, CurrentFormatter);
192        }

193
194        /// <summary>
195        ///  从ConfigFileName指定文件以CurrentSerializeType读取实例
196        ///  如果不存在则以InitConfig初始化类,创建并保存文件
197        /// </summary>
198        /// <param name="configFileFullName">缓存文件绝对路径</param>
199        /// <param name="serializeType"></param>
200        /// <param name="BackupOnError">读取错误时是否备份</param>
201        /// <returns></returns>

202        protected T Read(string configFileFullName, bool BackupOnError, Formatter serializeType)
203        {
204            T t = CacheUtility.Get<T>(CacheKEY);
205            if (t != null)
206                return t;
207            FileInfo fi = new FileInfo(configFileFullName);
208            if (fi.Exists)
209            {
210
211                FileStream fs = null;
212                try
213                {
214                    open the stream
236
237                    if (fs != null)
238                        fs.Close();
239                }

240                catch (Exception ex)
241                {
242                    if (fs != null)
243                        fs.Close();
244                    t = CustomizingInit();
245
246                    读取失败 进行备份 防止以后使用默认配置覆盖当前数据
262
263                    t.Exception = new Exception("读取配置文件时发生错误!将返回CustomizingInit()方法的实例,默认为 new T()!", ex);
264                }

265                finally
266                {
267
268                }

269            }

270            else
271            {
272                t = CustomizingInit();
273
274                //不存在的同一文件不能读多次
275                //防止在CustomizingInit()方法中调用Read(string configFileName, SerializeType serializeType) 造成死循环
276                string ProtectedKEY = Thread.CurrentThread.ManagedThreadId + fi.FullName + "init";
277                if (CacheUtility.GetAnyType<bool>(ProtectedKEY) == false)
278                {
279                    CacheUtility.SetAbsoluteExpiration(ProtectedKEY, truenull0.02);
280                }

281                else
282                {
283                    CacheUtility.Remove(ProtectedKEY);
284                    throw new Exception("'" + fi.FullName + "' 文件不存在!读取过于频繁。导致此保护异常发生。");
285                }

286                t.Exception = new Exception("配置文件:'" + fi.FullName + "' 不存在!默认返回CustomizingInit()方法返回的实例。");
287            }

288            if (t == null)
289                t.Exception = new Exception("发生错误,请检查初始化配置方法 CustomizingInit() 未返回的配置实例不能为空,或者系统中存在缓存 key :" + CacheKEY);
290            return t;
291        }

292
293#if DEBUG
294        private static void CallR(string key, object obj, CacheItemRemovedReason re)
295        {
296#if txtLogAll
297            Log.WriteLog(key + "::::" + re.ToString());
298#endif
299        }

300#endif
301
302        #endregion

303
304        保存
446
447        删除配置文件
476
477        #region  抽象成员
478        /// <summary>
479        /// 返回派生类的当前实例
480        /// protected override T Current
481        /// {
482        ///     get
483        ///     {
484        ///         return this;
485        ///     }
486        /// } 
487        /// </summary>

488        protected abstract T Current
489        {
490            get;
491        }

492        /// <summary>
493        /// 自定义初始化配置类
494        /// 获取 T 的配置实例时,如果配置文件不存在或者读取失败时返回此实例
495        /// 重写中一般读取备份的配置文件,必须保证备份配置文件存在,否则发生异常。
496        /// 默认返回    new T();
497        /// </summary>
498        /// <returns></returns>

499        protected virtual T CustomizingInit()
500        {
501            return Current;
502        }

503        /// <summary>
504        /// 配置文件名
505        /// <c>配置文件名</c>
506        /// <example>
507        /// 配置文件名
508        /// </example>
509        /// </summary>

510        private string ___file = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Config/" + typeof(T).Name + ".cfg");
511        /// <summary>
512        /// 配置文件全路径名
513        /// 默认:winform 在应用程序目录;web应用程序默认bin目录。
514        /// </summary>

515        [XmlIgnore]
516        public virtual string ConfigFileFullName
517        {
518            get
519            {
520                return ___file;
521            }

522            set
523            {
524                ___file = value;
525            }

526        }

527        #endregion

528    }

529}

posted @ 2011-04-29 14:31  likunran  阅读(166)  评论(0编辑  收藏  举报