[CommunityServer]Serializer序列化类
好久没有写博客了,今天终于有点时间来继续写写东西,今天我们来看一下Serializer序列化类,在CommunityServer中这个实例的存储方法很值得我们学习,在加入属性是在数据库中就不需要添加字段名。能够实现这种功能的做法就是通过序列化和反序列化来完成这项功能,将属性序列化为XML格式的文本存储与数据库中的一个NText字段中。
好久没有写博客了,今天终于有点时间来继续写写东西,今天我们来看一下Serializer序列化类,在CommunityServer中这个实例的存储方法很值得我们学习,在加入属性是在数据库中就不需要添加字段名。能够实现这种功能的做法就是通过序列化和反序列化来完成这项功能,将属性序列化为XML格式的文本存储与数据库中的一个NText字段中。
我们来看看这个类的代码,上面有我的注释,获取有些地方说得不正确,那也没办法啦!

序列化
1
/**//// <summary>
2
/// 序列化类。
3
/// </summary>
4
public class Serializer
5
{
6
//防止被实例化。
7
private Serializer()
8
{
9
10
}
11
/**//// <summary>
12
/// 静态构造函数仅在设置CanBinarySerialize值中使用一次。
13
/// </summary>
14
static Serializer()
15
{
16
SecurityPermission sp = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
17
try
18
{
19
sp.Demand();
20
CanBinarySerialize = true;
21
}
22
catch (SecurityException)
23
{
24
CanBinarySerialize = false;
25
}
26
}
27
/**//// <summary>
28
/// 获取二进制序列化是否被使用。
29
/// </summary>
30
public static readonly bool CanBinarySerialize;
31
/**//// <summary>
32
/// 将对象转化成二进制的数组。
33
/// </summary>
34
/// <param name="objectToConvert">用于转化的对象。</param>
35
/// <returns>返回转化后的数组,如果CanBinarySerialize为false则返回null。</returns>
36
public static byte[] ConvertToBytes(object objectToConvert)
37
{
38
byte[] byteArray = null;
39
40
if (CanBinarySerialize)
41
{
42
BinaryFormatter binaryFormatter = new BinaryFormatter();
43
using (MemoryStream ms = new MemoryStream())
44
{
45
46
binaryFormatter.Serialize(ms, objectToConvert);
47
//设置是内存存储位置为0。
48
ms.Position = 0;
49
//读取数组。
50
byteArray = new Byte[ms.Length];
51
ms.Read(byteArray, 0, byteArray.Length);
52
ms.Close();
53
}
54
}
55
return byteArray;
56
}
57
/**//// <summary>
58
/// 将对象以二进制形式存储到硬盘中。
59
/// </summary>
60
/// <param name="objectToSave">用于保存的对象。</param>
61
/// <param name="path">文件路径。</param>
62
/// <returns>如果存储成功则返回true,否则返回false。</returns>
63
public static bool SaveAsBinary(object objectToSave, string path)
64
{
65
if (objectToSave != null && CanBinarySerialize)
66
{
67
byte[] ba = ConvertToBytes(objectToSave);
68
if (ba != null)
69
{
70
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
71
{
72
using (BinaryWriter bw = new BinaryWriter(fs))
73
{
74
bw.Write(ba);
75
return true;
76
}
77
}
78
}
79
}
80
return false;
81
}
82
/**//// <summary>
83
///将对象转化为XML格式文件,该对象必须用[Serialize]标记,否则将抛出错误。
84
/// </summary>
85
/// <param name="objectToConvert">用于序列化的标记。</param>
86
/// <returns>返回XML文本,如果对象为空则返回null。</returns>
87
public static string ConvertToString(object objectToConvert)
88
{
89
string xml = null;
90
91
if (objectToConvert != null)
92
{
93
//获取当前序列化对象。
94
Type t = objectToConvert.GetType();
95
96
XmlSerializer ser = new XmlSerializer(t);
97
//将序列化的结果保存到XML中。
98
using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
99
{
100
ser.Serialize(writer, objectToConvert);
101
xml = writer.ToString();
102
writer.Close();
103
}
104
}
105
106
return xml;
107
}
108
/**//// <summary>
109
/// 将对象序列化后以XML格式存储于文件中。
110
/// </summary>
111
/// <param name="objectToConvert">用于序列化的对象。</param>
112
/// <param name="path">用于存储的文件路径。</param>
113
public static void SaveAsXML(object objectToConvert, string path)
114
{
115
if (objectToConvert != null)
116
{
117
Type t = objectToConvert.GetType();
118
119
XmlSerializer ser = new XmlSerializer(t);
120
121
using (StreamWriter writer = new StreamWriter(path))
122
{
123
ser.Serialize(writer, objectToConvert);
124
writer.Close();
125
}
126
}
127
128
}
129
/**//// <summary>
130
/// 将一个二进制的数组转化为对象,必须通过类型转化自己想得到的相应对象。如果数组为空则返回空。
131
/// </summary>
132
/// <param name="byteArray">用于转化的二进制数组。</param>
133
/// <returns>返回转化后的对象实例,如果数组为空,则返回空对象。</returns>
134
public static object ConvertToObject(byte[] byteArray)
135
{
136
object convertedObject = null;
137
if (CanBinarySerialize && byteArray != null && byteArray.Length > 0)
138
{
139
BinaryFormatter binaryFormatter = new BinaryFormatter();
140
using (MemoryStream ms = new MemoryStream())
141
{
142
ms.Write(byteArray, 0, byteArray.Length);
143
144
ms.Position = 0;
145
146
if (byteArray.Length > 4)
147
convertedObject = binaryFormatter.Deserialize(ms);
148
149
ms.Close();
150
}
151
}
152
return convertedObject;
153
}
154
/**//// <summary>
155
/// 将文件的数据转化为对象。
156
/// </summary>
157
/// <param name="path">文件路径。</param>
158
/// <param name="objectType">希望得到的对象。</param>
159
/// <returns>返回反序列化的对象。</returns>
160
public static object ConvertFileToObject(string path, Type objectType)
161
{
162
object convertedObject = null;
163
164
if (path != null && path.Length > 0)
165
{
166
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
167
{
168
XmlSerializer ser = new XmlSerializer(objectType);
169
convertedObject = ser.Deserialize(fs);
170
fs.Close();
171
}
172
}
173
return convertedObject;
174
}
175
/**//// <summary>
176
/// 将XML格式的字符串反序列化为实例对象。
177
/// </summary>
178
/// <param name="xml">Xml格式字符串。</param>
179
/// <param name="objectType">反序列化后所期望的对象。</param>
180
/// <returns>反序列化后所期望的对象,如果字符串为空,则返回空对象。</returns>
181
public static object ConvertToObject(string xml, Type objectType)
182
{
183
object convertedObject = null;
184
185
if (!WebHelper.IsNullOrEmpty(xml))
186
{
187
using (StringReader reader = new StringReader(xml))
188
{
189
XmlSerializer ser = new XmlSerializer(objectType);
190
convertedObject = ser.Deserialize(reader);
191
reader.Close();
192
}
193
}
194
return convertedObject;
195
}
196
/**//// <summary>
197
/// 将XML节点反序列化为实例对象。
198
/// </summary>
199
/// <param name="xml">用于反序列化的XML节点。</param>
200
/// <param name="objectType">反序列化后所期望的对象。</param>
201
/// <returns>反序列化后所期望的对象,如果字符串为空,则返回空对象。</returns>
202
public static object ConvertToObject(XmlNode node, Type objectType)
203
{
204
object convertedObject = null;
205
206
if (node != null)
207
{
208
using (StringReader reader = new StringReader(node.OuterXml))
209
{
210
211
XmlSerializer ser = new XmlSerializer(objectType);
212
213
convertedObject = ser.Deserialize(reader);
214
215
reader.Close();
216
}
217
}
218
return convertedObject;
219
}
220
/**//// <summary>
221
/// 加载一个二进制文件并将其转化为实例对象。
222
/// </summary>
223
/// <param name="path">文件路径。</param>
224
/// <returns>返回转化后的实例对象。</returns>
225
public static object LoadBinaryFile(string path)
226
{
227
if (!File.Exists(path))
228
return null;
229
230
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
231
{
232
BinaryReader br = new BinaryReader(fs);
233
byte[] ba = new byte[fs.Length];
234
br.Read(ba, 0, (int)fs.Length);
235
return ConvertToObject(ba);
236
}
237
}
238
/**//// <summary>
239
/// 将字符串序列化<see cref="System.Collections.Specialized.NameValueCollection"/>类型,第一个为键,第二位与其相对应的值。
240
/// </summary>
241
/// <param name="keys">NameValueCollection中的keys键。</param>
242
/// <param name="values">NameValueCollection中的keys键对应的value。</param>
243
/// <returns>基于key-value格式的NameValeCollection集合对象。</returns>
244
/// <example>
245
/// string keys = "key1:S:0:3:key2:S:3:2:";
246
/// string values = "12345";
247
/// 则这个所得的NameValueCollection结果中包含两个键(key1和key2),他们所对应的值分别为(123和45)。
248
/// 其中:"key1:S:0:3"的key1表示键,S表示字符类型,0表示values起始的位置,3表示values结束的位置。
249
/// </example>
250
public static NameValueCollection ConvertToNameValueCollection(string keys, string values)
251
{
252
NameValueCollection nvc = new NameValueCollection();
253
254
if (keys != null && values != null && keys.Length > 0 && values.Length > 0)
255
{
256
char[] splitter = new char[1]
{ ':' };
257
string[] keyNames = keys.Split(splitter);
258
259
for (int i = 0; i < (keyNames.Length / 4); i++)
260
{
261
int start = int.Parse(keyNames[(i * 4) + 2], CultureInfo.InvariantCulture);
262
int len = int.Parse(keyNames[(i * 4) + 3], CultureInfo.InvariantCulture);
263
string key = keyNames[i * 4];
264
265
//Future version will support more complex types
266
if (((keyNames[(i * 4) + 1] == "S") && (start >= 0)) && (len > 0) && (values.Length >= (start + len)))
267
{
268
nvc[key] = values.Substring(start, len);
269
}
270
}
271
}
272
273
return nvc;
274
}
275
/**//// <summary>
276
/// 基于NameValueCollection对象序列化成keys和values的字符串。
277
/// </summary>
278
/// <param name="nvc">用于序列化的NameValueCollection对象。</param>
279
/// <param name="keys">ref格式的参数keys将转化为NameValueCollection中的key。</param>
280
/// <param name="values">ref格式的参数values将转化为NameValueCollection中的value。</param>
281
public static void ConvertFromNameValueCollection(NameValueCollection nvc, ref string keys, ref string values)
282
{
283
if (nvc == null || nvc.Count == 0)
284
return;
285
286
StringBuilder sbKey = new StringBuilder();
287
StringBuilder sbValue = new StringBuilder();
288
289
int index = 0;
290
foreach (string key in nvc.AllKeys)
291
{
292
if (key.IndexOf(':') != -1)
293
throw new ArgumentException("ExtendedAttributes Key can not contain the character \":\"");
294
295
string v = nvc[key];
296
if (!WebHelper.IsNullOrEmpty(v))
297
{
298
sbKey.AppendFormat("{0}:S:{1}:{2}:", key, index, v.Length);
299
sbValue.Append(v);
300
index += v.Length;
301
}
302
}
303
keys = sbKey.ToString();
304
values = sbValue.ToString();
305
}
306
}
在SiteSettings.cs中可以发现有些属性加有[XmlIgnore]标记,这是在序列化和反序列化时对该属性都不起作用,如SettingsID等在数据库中都已经存在字段名。从代码中我们可以看到,将一个NameValueCollection集合序列化和反序列化,其实键和值对存储在一个结构中,这个结构就是:
其他的源代码都有解释了,应该能搞懂里面的东西!
我们来看看这个类的代码,上面有我的注释,获取有些地方说得不正确,那也没办法啦!
1

/**//// <summary>2
/// 序列化类。3
/// </summary>4
public class Serializer5

{6
//防止被实例化。7
private Serializer()8

{9

10
}11

/**//// <summary>12
/// 静态构造函数仅在设置CanBinarySerialize值中使用一次。13
/// </summary>14
static Serializer()15

{16
SecurityPermission sp = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);17
try18

{19
sp.Demand();20
CanBinarySerialize = true;21
}22
catch (SecurityException)23

{24
CanBinarySerialize = false;25
}26
}27

/**//// <summary>28
/// 获取二进制序列化是否被使用。29
/// </summary>30
public static readonly bool CanBinarySerialize;31

/**//// <summary>32
/// 将对象转化成二进制的数组。33
/// </summary>34
/// <param name="objectToConvert">用于转化的对象。</param>35
/// <returns>返回转化后的数组,如果CanBinarySerialize为false则返回null。</returns>36
public static byte[] ConvertToBytes(object objectToConvert)37

{38
byte[] byteArray = null;39

40
if (CanBinarySerialize)41

{42
BinaryFormatter binaryFormatter = new BinaryFormatter();43
using (MemoryStream ms = new MemoryStream())44

{45

46
binaryFormatter.Serialize(ms, objectToConvert);47
//设置是内存存储位置为0。48
ms.Position = 0;49
//读取数组。50
byteArray = new Byte[ms.Length];51
ms.Read(byteArray, 0, byteArray.Length);52
ms.Close();53
}54
}55
return byteArray;56
}57

/**//// <summary>58
/// 将对象以二进制形式存储到硬盘中。59
/// </summary>60
/// <param name="objectToSave">用于保存的对象。</param>61
/// <param name="path">文件路径。</param>62
/// <returns>如果存储成功则返回true,否则返回false。</returns>63
public static bool SaveAsBinary(object objectToSave, string path)64

{65
if (objectToSave != null && CanBinarySerialize)66

{67
byte[] ba = ConvertToBytes(objectToSave);68
if (ba != null)69

{70
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))71

{72
using (BinaryWriter bw = new BinaryWriter(fs))73

{74
bw.Write(ba);75
return true;76
}77
}78
}79
}80
return false;81
}82

/**//// <summary>83
///将对象转化为XML格式文件,该对象必须用[Serialize]标记,否则将抛出错误。84
/// </summary>85
/// <param name="objectToConvert">用于序列化的标记。</param>86
/// <returns>返回XML文本,如果对象为空则返回null。</returns>87
public static string ConvertToString(object objectToConvert)88

{89
string xml = null;90

91
if (objectToConvert != null)92

{93
//获取当前序列化对象。94
Type t = objectToConvert.GetType();95

96
XmlSerializer ser = new XmlSerializer(t);97
//将序列化的结果保存到XML中。98
using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))99

{100
ser.Serialize(writer, objectToConvert);101
xml = writer.ToString();102
writer.Close();103
}104
}105

106
return xml;107
}108

/**//// <summary>109
/// 将对象序列化后以XML格式存储于文件中。110
/// </summary>111
/// <param name="objectToConvert">用于序列化的对象。</param>112
/// <param name="path">用于存储的文件路径。</param>113
public static void SaveAsXML(object objectToConvert, string path)114

{115
if (objectToConvert != null)116

{117
Type t = objectToConvert.GetType();118

119
XmlSerializer ser = new XmlSerializer(t);120

121
using (StreamWriter writer = new StreamWriter(path))122

{123
ser.Serialize(writer, objectToConvert);124
writer.Close();125
}126
}127

128
}129

/**//// <summary>130
/// 将一个二进制的数组转化为对象,必须通过类型转化自己想得到的相应对象。如果数组为空则返回空。131
/// </summary>132
/// <param name="byteArray">用于转化的二进制数组。</param>133
/// <returns>返回转化后的对象实例,如果数组为空,则返回空对象。</returns>134
public static object ConvertToObject(byte[] byteArray)135

{136
object convertedObject = null;137
if (CanBinarySerialize && byteArray != null && byteArray.Length > 0)138

{139
BinaryFormatter binaryFormatter = new BinaryFormatter();140
using (MemoryStream ms = new MemoryStream())141

{142
ms.Write(byteArray, 0, byteArray.Length);143

144
ms.Position = 0;145

146
if (byteArray.Length > 4)147
convertedObject = binaryFormatter.Deserialize(ms);148

149
ms.Close();150
}151
}152
return convertedObject;153
}154

/**//// <summary>155
/// 将文件的数据转化为对象。156
/// </summary>157
/// <param name="path">文件路径。</param>158
/// <param name="objectType">希望得到的对象。</param>159
/// <returns>返回反序列化的对象。</returns>160
public static object ConvertFileToObject(string path, Type objectType)161

{162
object convertedObject = null;163

164
if (path != null && path.Length > 0)165

{166
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))167

{168
XmlSerializer ser = new XmlSerializer(objectType);169
convertedObject = ser.Deserialize(fs);170
fs.Close();171
}172
}173
return convertedObject;174
}175

/**//// <summary>176
/// 将XML格式的字符串反序列化为实例对象。 177
/// </summary>178
/// <param name="xml">Xml格式字符串。</param>179
/// <param name="objectType">反序列化后所期望的对象。</param>180
/// <returns>反序列化后所期望的对象,如果字符串为空,则返回空对象。</returns>181
public static object ConvertToObject(string xml, Type objectType)182

{183
object convertedObject = null;184

185
if (!WebHelper.IsNullOrEmpty(xml))186

{187
using (StringReader reader = new StringReader(xml))188

{189
XmlSerializer ser = new XmlSerializer(objectType);190
convertedObject = ser.Deserialize(reader);191
reader.Close();192
}193
}194
return convertedObject;195
}196

/**//// <summary>197
/// 将XML节点反序列化为实例对象。 198
/// </summary>199
/// <param name="xml">用于反序列化的XML节点。</param>200
/// <param name="objectType">反序列化后所期望的对象。</param>201
/// <returns>反序列化后所期望的对象,如果字符串为空,则返回空对象。</returns>202
public static object ConvertToObject(XmlNode node, Type objectType)203

{204
object convertedObject = null;205

206
if (node != null)207

{208
using (StringReader reader = new StringReader(node.OuterXml))209

{210

211
XmlSerializer ser = new XmlSerializer(objectType);212

213
convertedObject = ser.Deserialize(reader);214

215
reader.Close();216
}217
}218
return convertedObject;219
}220

/**//// <summary>221
/// 加载一个二进制文件并将其转化为实例对象。222
/// </summary>223
/// <param name="path">文件路径。</param>224
/// <returns>返回转化后的实例对象。</returns>225
public static object LoadBinaryFile(string path)226

{227
if (!File.Exists(path))228
return null;229

230
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))231

{232
BinaryReader br = new BinaryReader(fs);233
byte[] ba = new byte[fs.Length];234
br.Read(ba, 0, (int)fs.Length);235
return ConvertToObject(ba);236
}237
}238

/**//// <summary>239
/// 将字符串序列化<see cref="System.Collections.Specialized.NameValueCollection"/>类型,第一个为键,第二位与其相对应的值。240
/// </summary>241
/// <param name="keys">NameValueCollection中的keys键。</param>242
/// <param name="values">NameValueCollection中的keys键对应的value。</param>243
/// <returns>基于key-value格式的NameValeCollection集合对象。</returns>244
/// <example>245
/// string keys = "key1:S:0:3:key2:S:3:2:";246
/// string values = "12345";247
/// 则这个所得的NameValueCollection结果中包含两个键(key1和key2),他们所对应的值分别为(123和45)。248
/// 其中:"key1:S:0:3"的key1表示键,S表示字符类型,0表示values起始的位置,3表示values结束的位置。249
/// </example>250
public static NameValueCollection ConvertToNameValueCollection(string keys, string values)251

{252
NameValueCollection nvc = new NameValueCollection();253

254
if (keys != null && values != null && keys.Length > 0 && values.Length > 0)255

{256

char[] splitter = new char[1]
{ ':' };257
string[] keyNames = keys.Split(splitter);258

259
for (int i = 0; i < (keyNames.Length / 4); i++)260

{261
int start = int.Parse(keyNames[(i * 4) + 2], CultureInfo.InvariantCulture);262
int len = int.Parse(keyNames[(i * 4) + 3], CultureInfo.InvariantCulture);263
string key = keyNames[i * 4];264

265
//Future version will support more complex types 266
if (((keyNames[(i * 4) + 1] == "S") && (start >= 0)) && (len > 0) && (values.Length >= (start + len)))267

{268
nvc[key] = values.Substring(start, len);269
}270
}271
}272

273
return nvc;274
}275

/**//// <summary>276
/// 基于NameValueCollection对象序列化成keys和values的字符串。277
/// </summary>278
/// <param name="nvc">用于序列化的NameValueCollection对象。</param>279
/// <param name="keys">ref格式的参数keys将转化为NameValueCollection中的key。</param>280
/// <param name="values">ref格式的参数values将转化为NameValueCollection中的value。</param>281
public static void ConvertFromNameValueCollection(NameValueCollection nvc, ref string keys, ref string values)282

{283
if (nvc == null || nvc.Count == 0)284
return;285

286
StringBuilder sbKey = new StringBuilder();287
StringBuilder sbValue = new StringBuilder();288

289
int index = 0;290
foreach (string key in nvc.AllKeys)291

{292
if (key.IndexOf(':') != -1)293
throw new ArgumentException("ExtendedAttributes Key can not contain the character \":\"");294

295
string v = nvc[key];296
if (!WebHelper.IsNullOrEmpty(v))297

{298
sbKey.AppendFormat("{0}:S:{1}:{2}:", key, index, v.Length);299
sbValue.Append(v);300
index += v.Length;301
}302
}303
keys = sbKey.ToString();304
values = sbValue.ToString();305
}306
}在SiteSettings.cs中可以发现有些属性加有[XmlIgnore]标记,这是在序列化和反序列化时对该属性都不起作用,如SettingsID等在数据库中都已经存在字段名。从代码中我们可以看到,将一个NameValueCollection集合序列化和反序列化,其实键和值对存储在一个结构中,这个结构就是:
1
public struct SerializerData
2
{
3
/**//// <summary>
4
/// 序列化NameValueCollection集合时用于保存Keys的字符串。
5
/// </summary>
6
public string Keys;
7
/**//// <summary>
8
/// 序列化NameValueCollection集合时用于保存Values的字符串。
9
/// </summary>
10
public string Values;
11
}
public struct SerializerData2

{3

/**//// <summary>4
/// 序列化NameValueCollection集合时用于保存Keys的字符串。5
/// </summary>6
public string Keys;7

/**//// <summary>8
/// 序列化NameValueCollection集合时用于保存Values的字符串。9
/// </summary>10
public string Values;11
}其他的源代码都有解释了,应该能搞懂里面的东西!


浙公网安备 33010602011771号