.net 序列化通用的方法
1
//是否写日志
2
#define txtLogAll
3
4
using System;
5
using System.Web;
6
using System.Xml.Serialization;
7
using System.IO;
8
using System.Runtime.Serialization;
9
using System.Runtime.Serialization.Formatters.Soap;
10
using System.Runtime.Serialization.Formatters.Binary;
11
using System.Web.Caching;
12
using System.Threading;
13
using tjb.Utility.Caching;
14
using System.Xml;
15
using System.Text;
16
17
18
namespace 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, true, null, 0.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
}


浙公网安备 33010602011771号