通用序列化基类 只须实现该类抽象成员即可进行序列化与反序列化
转载请注明出处 http://www.cnblogs.com/68681395
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
文件序列化的类型#region 文件序列化的类型
22
/**//// <summary>
23
/// 序列化文件的方式
24
/// Binary,Xml,SoapXml
25
/// </summary>
26
public enum Formatter
27
{
28
/**//// <summary>
29
/// 字节
30
/// </summary>
31
Binary,
32
/**//// <summary>
33
/// xml
34
/// </summary>
35
Xml,
36
/**//// <summary>
37
/// soap协议的xml
38
/// </summary>
39
SoapXml
40
}
41
#endregion
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
Exceptions#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
Caching..#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
#region open the stream
215
// open the stream
216
fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
217
IFormatter formatter = null;
218
switch (serializeType)
219
{
220
case Formatter.Binary:
221
formatter = new BinaryFormatter();
222
t = formatter.Deserialize(fs) as T;
223
break;
224
case Formatter.SoapXml:
225
formatter = new SoapFormatter();
226
t = formatter.Deserialize(fs) as T;
227
break;
228
case Formatter.Xml:
229
XmlSerializer serializer = new XmlSerializer(typeof(T));
230
t = serializer.Deserialize(fs) as T;
231
break;
232
default:
233
break;
234
}
235
#endregion
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
读取失败 进行备份 防止以后使用默认配置覆盖当前数据#region 读取失败 进行备份 防止以后使用默认配置覆盖当前数据
247
if (BackupOnError)
248
if (fi.Exists)
249
{
250
string BackupFilePath = fi.FullName + ".Read." + DateTime.Now.ToString("yyMMddHHssfff") + ".bak";
251
try
252
{
253
fi.CopyTo(BackupFilePath, true);
254
t.Save(true);
255
}
256
catch (Exception ioex)
257
{
258
t.Exception = new Exception("读取配置文件出错后,对配置文件进行备份发生错误!", ioex);
259
}
260
}
261
#endregion
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
保存#region 保存
305
/**//// <summary>
306
/// 将当前实例进行保存
307
/// </summary>
308
/// <param name="BackupOnError">发生错误时是否备份</param>
309
/// <returns></returns>
310
public bool Save(bool BackupOnError)
311
{
312
if (Current == null)
313
{
314
Exception = new Exception(typeof(T).FullName + " 未正确实现 Current;");
315
return false;
316
}
317
return Save(Current, BackupOnError);
318
}
319
/**//// <summary>
320
/// 将当前实例进行保存
321
/// 发生错误时将备份配置文件
322
/// </summary>
323
/// <returns></returns>
324
public virtual bool Save()
325
{
326
return Save(true);
327
}
328
329
/**//// <summary>
330
/// 将当前实例保存到T.ConfigFileName指定的配置文件
331
/// </summary>
332
/// <param name="Tobj"></param>
333
/// <param name="BackupOnError"></param>
334
/// <returns></returns>
335
public bool Save(T Tobj, bool BackupOnError)
336
{
337
return SaveAs(Tobj, ConfigFileFullName, BackupOnError);
338
}
339
340
/**//// <summary>
341
/// 将一个实例对象保存到FileFullName指定的配置文件
342
/// </summary>
343
/// <param name="FileFullName"></param>
344
/// <param name="Tobj"></param>
345
/// <param name="BackupOnError"></param>
346
/// <returns></returns>
347
protected bool SaveAs(T Tobj, string FileFullName, bool BackupOnError)
348
{
349
lock (typeof(T))
350
{
351
if (Tobj == default(T))
352
{
353
Exception = new Exception(typeof(T).FullName + " 未正确实现 Current;");
354
return false;
355
}
356
FileStream fs = null;
357
FileInfo fi = new FileInfo(FileFullName);
358
string BackupFilePath = null;
359
360
if (BackupOnError)
361
{
362
backup#region backup
363
364
BackupFilePath = fi.FullName + ".Save." + DateTime.Now.ToString("yyMMddHHssfff") + ".bak";
365
try
366
{
367
//如果存在先备份
368
if (fi.Exists)
369
{
370
fi.CopyTo(BackupFilePath, true);
371
}
372
else if (!fi.Directory.Exists)
373
{
374
//目录不存在创建目录
375
fi.Directory.Create();
376
}
377
}
378
catch (Exception ex)
379
{
380
Tobj.Exception = new Exception("备份配置文件时发生错误!", ex);
381
return false;
382
}
383
#endregion
384
}
385
386
try
387
{
388
if (fi.Exists)
389
fi.Delete();
390
serialize it
#region serialize it
391
fs = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write, FileShare.Read);
392
IFormatter formatter = null;
393
switch (CurrentFormatter)
394
{
395
case Formatter.Binary:
396
formatter = new BinaryFormatter();
397
formatter.Serialize(fs, Tobj);
398
break;
399
case Formatter.SoapXml:
400
formatter = new SoapFormatter();
401
formatter.Serialize(fs, Tobj);
402
break;
403
case Formatter.Xml:
404
XmlSerializer serializer = new XmlSerializer(typeof(T));
405
406
serializer.Serialize(fs, Tobj);
407
break;
408
default:
409
break;
410
}
411
#endregion
412
413
//成功则删除当前备份
414
415
成功则删除当前备份#region 成功则删除当前备份
416
if (BackupOnError)
417
try
418
{
419
File.Delete(BackupFilePath);
420
}
421
catch (Exception ex)
422
{
423
Tobj.Exception = new Exception("删除备份文件时发生错误!", ex);
424
}
425
#endregion
426
427
return true;
428
}
429
catch (Exception ex)
430
{
431
#if txtLog
432
Log.WriteLog(ex);
433
#endif
434
Tobj.Exception = new Exception("保存配置文件时发生错误!", ex);
435
436
return false;
437
}
438
finally
439
{
440
if (fs != null)
441
fs.Close();
442
}
443
}
444
}
445
#endregion
446
447
删除配置文件#region 删除配置文件
448
/**//// <summary>
449
/// 删除配置文件
450
/// </summary>
451
/// <returns></returns>
452
public bool Delete()
453
{
454
return Delete(ConfigFileFullName);
455
}
456
/**//// <summary>
457
/// 删除指定的配置文件 .文件不存在不引发异常。并返回true
458
/// </summary>
459
/// <param name="FileFullName"></param>
460
/// <returns></returns>
461
public bool Delete(string FileFullName)
462
{
463
try
464
{
465
if (File.Exists(FileFullName))
466
File.Delete(FileFullName);
467
return true;
468
}
469
catch (Exception ex)
470
{
471
Current.Exception = ex;
472
return false;
473
}
474
}
475
#endregion
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
}
530
//是否写日志2
#define txtLogAll3

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.Config19


{20

21

文件序列化的类型#region 文件序列化的类型22

/**//// <summary>23
/// 序列化文件的方式24
/// Binary,Xml,SoapXml25
/// </summary>26
public enum Formatter27

{28

/**//// <summary>29
/// 字节30
/// </summary>31
Binary,32

/**//// <summary>33
/// xml34
/// </summary>35
Xml,36

/**//// <summary>37
/// soap协议的xml38
/// </summary>39
SoapXml40
}41
#endregion42

43

/**//// <summary>44
/// 序列化基类 by Tjb 2007/06 45
/// T 类型不能创建多态的多个实例46
/// 优化和修正,增加配置文件备份 2008/9/1847
/// 修改:获取实例时加锁48
/// 修改:49
/// SaveAs(T Tobj, string FileFullName, bool BackupOnError) 方法增加线程锁定。防止多线程冲突 2008/10/2450
/// </summary>51
/// <typeparam name="T">T 必须有无参数的构造函数</typeparam>52
[Serializable]53
public abstract class IConfig<T> where T : IConfig<T>, new()54

{55

56

Exceptions#region Exceptions57
private Exception __ConfigException;58

/**//// <summary>59
/// 读取或保存时发生的错误60
/// </summary>61
[XmlIgnore, SoapIgnore]62
public Exception Exception63

{64
get65

{66
return __ConfigException;67
}68
private set69

{70
if (value != null)71

{72
HasError = true;73
__ConfigException = value;74
#if txtLogAll75
Log.WriteLog(value);76
#endif77
}78
}79
}80
private bool __HasError = false;81

/**//// <summary>82
/// 获取一个值 指示读取或者保存时是否发生错误83
/// 如果当前错误被获取后,此标志将被置为false84
/// </summary>85
[XmlIgnore, SoapIgnore]86
public bool HasError87

{88

get
{ return __HasError; }89

private set
{ __HasError = value; }90
}91
#endregion92

93

序列化类型 可重写#region 序列化类型 可重写94

95
private Formatter _CurrentFormatter = Formatter.Xml;96

/**//// <summary>97
/// 序列化的方式98
/// </summary> 99
[XmlIgnore]100
protected virtual Formatter CurrentFormatter101

{102
get103

{104
return _CurrentFormatter;105
}106
set107

{108
_CurrentFormatter = value;109
}110
}111

112
#endregion113

114

获取单个实例#region 获取单个实例115

116

/**//// <summary>117
/// 获取Cache中缓存T的key118
/// </summary>119
public static string CacheKEY120

{121
get122

{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 Instance131

{132
get133

{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 DEBUG147
CacheUtility.SetSlidingExpiration(CacheKEY, c, c.ConfigFileFullName, 7, CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(CallR));148
#else149
CacheUtility.SetSlidingExpiration(CacheKEY, c, c.ConfigFileFullName, 7, CacheItemPriority.NotRemovable, null);150
#endif151
}152
}153
}154
return c;155
}156
}157

158
#endregion159

160

Caching..#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
#endregion180

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
try213

{214

open the stream
#region open the stream
215
// open the stream
216
fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);217
IFormatter formatter = null;218
switch (serializeType)219

{220
case Formatter.Binary:221
formatter = new BinaryFormatter();222
t = formatter.Deserialize(fs) as T;223
break;224
case Formatter.SoapXml:225
formatter = new SoapFormatter();226
t = formatter.Deserialize(fs) as T;227
break;228
case Formatter.Xml:229
XmlSerializer serializer = new XmlSerializer(typeof(T));230
t = serializer.Deserialize(fs) as T;231
break;232
default:233
break;234
}235
#endregion236

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

读取失败 进行备份 防止以后使用默认配置覆盖当前数据#region 读取失败 进行备份 防止以后使用默认配置覆盖当前数据247
if (BackupOnError)248
if (fi.Exists)249

{250
string BackupFilePath = fi.FullName + ".Read." + DateTime.Now.ToString("yyMMddHHssfff") + ".bak";251
try252

{253
fi.CopyTo(BackupFilePath, true);254
t.Save(true);255
}256
catch (Exception ioex)257

{258
t.Exception = new Exception("读取配置文件出错后,对配置文件进行备份发生错误!", ioex);259
}260
}261
#endregion262

263
t.Exception = new Exception("读取配置文件时发生错误!将返回CustomizingInit()方法的实例,默认为 new T()!", ex);264
}265
finally266

{267

268
}269
}270
else271

{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
else282

{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 DEBUG294
private static void CallR(string key, object obj, CacheItemRemovedReason re)295

{296
#if txtLogAll297
Log.WriteLog(key + "::::" + re.ToString());298
#endif299
}300
#endif301

302
#endregion303

304

保存#region 保存305

/**//// <summary>306
/// 将当前实例进行保存307
/// </summary>308
/// <param name="BackupOnError">发生错误时是否备份</param>309
/// <returns></returns>310
public bool Save(bool BackupOnError)311

{312
if (Current == null)313

{314
Exception = new Exception(typeof(T).FullName + " 未正确实现 Current;");315
return false;316
}317
return Save(Current, BackupOnError);318
}319

/**//// <summary>320
/// 将当前实例进行保存321
/// 发生错误时将备份配置文件322
/// </summary>323
/// <returns></returns>324
public virtual bool Save()325

{326
return Save(true);327
}328

329

/**//// <summary>330
/// 将当前实例保存到T.ConfigFileName指定的配置文件331
/// </summary>332
/// <param name="Tobj"></param>333
/// <param name="BackupOnError"></param>334
/// <returns></returns> 335
public bool Save(T Tobj, bool BackupOnError)336

{337
return SaveAs(Tobj, ConfigFileFullName, BackupOnError);338
}339

340

/**//// <summary>341
/// 将一个实例对象保存到FileFullName指定的配置文件342
/// </summary>343
/// <param name="FileFullName"></param>344
/// <param name="Tobj"></param>345
/// <param name="BackupOnError"></param>346
/// <returns></returns> 347
protected bool SaveAs(T Tobj, string FileFullName, bool BackupOnError)348

{349
lock (typeof(T))350

{351
if (Tobj == default(T))352

{353
Exception = new Exception(typeof(T).FullName + " 未正确实现 Current;");354
return false;355
}356
FileStream fs = null;357
FileInfo fi = new FileInfo(FileFullName);358
string BackupFilePath = null;359

360
if (BackupOnError)361

{362

backup#region backup363

364
BackupFilePath = fi.FullName + ".Save." + DateTime.Now.ToString("yyMMddHHssfff") + ".bak";365
try366

{367
//如果存在先备份368
if (fi.Exists)369

{370
fi.CopyTo(BackupFilePath, true);371
}372
else if (!fi.Directory.Exists)373

{374
//目录不存在创建目录375
fi.Directory.Create();376
}377
}378
catch (Exception ex)379

{380
Tobj.Exception = new Exception("备份配置文件时发生错误!", ex);381
return false;382
}383
#endregion384
}385

386
try387

{388
if (fi.Exists)389
fi.Delete();390

serialize it
#region serialize it
391
fs = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write, FileShare.Read);392
IFormatter formatter = null;393
switch (CurrentFormatter)394

{395
case Formatter.Binary:396
formatter = new BinaryFormatter();397
formatter.Serialize(fs, Tobj);398
break;399
case Formatter.SoapXml:400
formatter = new SoapFormatter();401
formatter.Serialize(fs, Tobj);402
break;403
case Formatter.Xml:404
XmlSerializer serializer = new XmlSerializer(typeof(T));405

406
serializer.Serialize(fs, Tobj);407
break;408
default:409
break;410
}411
#endregion412

413
//成功则删除当前备份414

415

成功则删除当前备份#region 成功则删除当前备份416
if (BackupOnError)417
try418

{419
File.Delete(BackupFilePath);420
}421
catch (Exception ex)422

{423
Tobj.Exception = new Exception("删除备份文件时发生错误!", ex);424
}425
#endregion426

427
return true;428
}429
catch (Exception ex)430

{431
#if txtLog432
Log.WriteLog(ex);433
#endif434
Tobj.Exception = new Exception("保存配置文件时发生错误!", ex);435

436
return false;437
}438
finally439

{440
if (fs != null)441
fs.Close();442
}443
}444
}445
#endregion446

447

删除配置文件#region 删除配置文件448

/**//// <summary>449
/// 删除配置文件450
/// </summary>451
/// <returns></returns>452
public bool Delete()453

{454
return Delete(ConfigFileFullName);455
}456

/**//// <summary>457
/// 删除指定的配置文件 .文件不存在不引发异常。并返回true458
/// </summary>459
/// <param name="FileFullName"></param>460
/// <returns></returns>461
public bool Delete(string FileFullName)462

{463
try464

{465
if (File.Exists(FileFullName))466
File.Delete(FileFullName);467
return true;468
}469
catch (Exception ex)470

{471
Current.Exception = ex;472
return false;473
}474
}475
#endregion476

477

抽象成员#region 抽象成员478

/**//// <summary>479
/// 返回派生类的当前实例480
/// protected override T Current481
/// {482
/// get483
/// {484
/// return this;485
/// }486
/// } 487
/// </summary>488
protected abstract T Current489

{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 ConfigFileFullName517

{518
get519

{520
return ___file;521
}522
set523

{524
___file = value;525
}526
}527
#endregion528
}529
}530

浙公网安备 33010602011771号