[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


2

3

4

5



6

7

8



9

10

11


12

13

14

15



16

17

18



19

20

21

22

23



24

25

26

27


28

29

30

31


32

33

34

35

36

37



38

39

40

41



42

43

44



45

46

47

48

49

50

51

52

53

54

55

56

57


58

59

60

61

62

63

64



65

66



67

68

69



70

71



72

73



74

75

76

77

78

79

80

81

82


83

84

85

86

87

88



89

90

91

92



93

94

95

96

97

98

99



100

101

102

103

104

105

106

107

108


109

110

111

112

113

114



115

116



117

118

119

120

121

122



123

124

125

126

127

128

129


130

131

132

133

134

135



136

137

138



139

140

141



142

143

144

145

146

147

148

149

150

151

152

153

154


155

156

157

158

159

160

161



162

163

164

165



166

167



168

169

170

171

172

173

174

175


176

177

178

179

180

181

182



183

184

185

186



187

188



189

190

191

192

193

194

195

196


197

198

199

200

201

202

203



204

205

206

207



208

209



210

211

212

213

214

215

216

217

218

219

220


221

222

223

224

225

226



227

228

229

230

231



232

233

234

235

236

237

238


239

240

241

242

243

244

245

246

247

248

249

250

251



252

253

254

255



256



257

258

259

260



261

262

263

264

265

266

267



268

269

270

271

272

273

274

275


276

277

278

279

280

281

282



283

284

285

286

287

288

289

290

291



292

293

294

295

296

297



298

299

300

301

302

303

304

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
}

2



3


4

5

6

7


8

9

10

11

其他的源代码都有解释了,应该能搞懂里面的东西!
分类:
CommunityServer
, ASP.NET
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架