深度序列化:带泛型的二进制和 SOAP 序列化






4.80/5 (12投票s)
2006年8月23日
2分钟阅读

56991

410
一个您可以包含在类库中的序列化类。
引言
您遇到以下问题之一
- 您需要将一个对象持久化到存储介质中。
- 您正在使用 RPC。
- 您需要流式传输到套接字。
解决方案
序列化允许您将对象图转换为线性的字节、XML 或 SOAP 序列。 一旦一个对象被扁平化,您就可以存储它或通过网络发送它。 然后可以对序列化数据进行反序列化。 反序列化本质上是重新构建您最初序列化的对象图。 序列化听起来很复杂,但实际上,它非常容易,因为 .NET 框架为您处理了大部分复杂性。
微软的 .NET 框架提供了两种不同的选项来持久化数据或通过网络发送数据:浅序列化和深序列化。 浅序列化允许序列化对象的读写属性值。 Private
数据成员和被序列化对象引用的对象被忽略。 浅序列化被 Web 服务和 XmlSerializer
使用。
正如您可能从这篇文章的标题中猜到的那样,本代码示例的重点是深序列化。 深序列化会序列化整个对象以及被序列化对象引用的任何对象。 此代码示例演示了如何使用 BinaryFormatter
和 SoapFormatter
来序列化数据。 这两个类都执行深序列化。
为了有资格进行序列化,一个对象必须使用 [Serializable]
属性进行修饰,或者实现 ISerializable
接口。 如果性能是一个问题,您可以通过使用 [NonSerialized]
属性修饰对象中的字段来选择从序列化中排除该字段 — 这称为选择性序列化。
我已经编写了以下代码示例来演示在您的项目中实现序列化是多么容易。
步骤 1:二进制序列化到字节数组
二进制序列化使用 BinaryFormatter
,它包含在 System.Runtime.Serialization.Formatters.Binary
namespace
中。 BinaryFormatter
类实现 IRemotingFormatter
接口以支持远程过程调用 (RPC),以及 IFormatter
接口(由 IRemotingFormatter
继承)以支持对象图的序列化。
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace CoreWebLibrary.Utility
{
public static class BinarySerialization
{
public static byte[] BinarySerialize(Object obj)
{
byte[] serializedObject;
MemoryStream ms = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
b.Serialize(ms, obj);
ms.Seek(0, 0);
serializedObject = ms.ToArray();
ms.Close();
return serializedObject;
}
public static T BinaryDeSerialize<T>(byte[] serializedObject)
{
MemoryStream ms = new MemoryStream();
ms.Write(serializedObject, 0, serializedObject.Length);
ms.Seek(0, 0);
BinaryFormatter b = new BinaryFormatter();
Object obj = b.Deserialize(ms);
ms.Close();
return (T)obj;
}
}
}
步骤 2:二进制序列化到文件
将二进制序列化到文件的一个示例
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace CoreWebLibrary.Utility
{
public static class FileSerialization
{
public static void FileSerialize(Object obj, string filePath)
{
FileStream fileStream = null;
try
{
fileStream = new FileStream(filePath, FileMode.Create);
BinaryFormatter b = new BinaryFormatter();
b.Serialize(fileStream, obj);
}
catch
{
throw;
}
finally
{
if (fileStream != null)
fileStream.Close();
}
}
public static T FileDeSerialize<T>(string filePath)
{
FileStream fileStream = null;
Object obj;
try
{
if (File.Exists(filePath) == false)
throw new FileNotFoundException("The file" +
" was not found.", filePath);
fileStream = new FileStream(filePath, FileMode.Open);
BinaryFormatter b = new BinaryFormatter();
obj = b.Deserialize(fileStream);
}
catch
{
throw;
}
finally
{
if (fileStream != null)
fileStream.Close();
}
return (T)obj;
}
}
}
步骤 3:SOAP 序列化到字符串
SOAP 序列化使用 SoapFormatter
,它包含在 System.Runtime.Serialization.Formatters.Soap
namespace
中。 SOAP 序列化比二进制序列化更通用,但通用性在性能方面付出了巨大的代价。
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;
using System.Text;
namespace CoreWebLibrary.Utility
{
public class SoapSerialization
{
public static string SoapMemoryStreamSerialization(object obj,
Encoding encodingType)
{
string xmlResult;
using (Stream stream = new MemoryStream())
{
try
{
SoapFormatter sf = new SoapFormatter();
sf.Serialize(stream, obj);
}
catch
{
throw;
}
stream.Position = 0;
byte[] b = new byte[stream.Length];
stream.Read(b, 0, (int)stream.Length);
xmlResult = encodingType.GetString(b, 0, b.Length);
}
return xmlResult;
}
public T SoapDeserailization<T>(string input,
System.Text.Encoding encodingType)
{
Object obj = null;
using (StringReader sr = new StringReader(input))
{
byte[] b;
b = encodingType.GetBytes(input);
Stream stream = new MemoryStream(b);
try
{
SoapFormatter sf = new SoapFormatter();
obj = (object)sf.Deserialize(stream);
}
catch
{
throw;
}
}
return (T)obj;
}
}
}
结论
如果您想成为一名有效的开发人员,了解序列化如何工作至关重要。 希望这个例子已经证明了深序列化的实现既简单又强大。
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。