.NET 常用的三种自动序列化的方式,Xml,Binary,Soap,现把代码整理一下,方便以后使用。
使用XmlSerializer序列化
使用Xml序列化是很多时候的最佳选择,我们在使用Xml序列化时,可以给它提供Schema控制序列化格式,这里就只提供默认的序列化与反序列化的代码。
private string WriteToXml<T>(T instance)
{
XmlSerializer xmlSerler = new XmlSerializer(instance.GetType());
XmlDocument xmlDoc = new XmlDocument();
StringBuilder strBuilder = new StringBuilder();
XmlWriter sw = XmlWriter.Create(strBuilder);
try
{
xmlSerler.Serialize(sw, instance);
return strBuilder.ToString();
}
catch (Exception exp)
{
throw exp;
}
finally
{
sw.Close();
}
}
private T ReadFromXml<T>(string str)
{
XmlSerializer xmlSerler = new XmlSerializer(typeof(T));
XmlReader xr = new XmlTextReader(new StringReader(str));
try
{
T instance = (T)xmlSerler.Deserialize(xr);
return instance;
}
catch (Exception exp)
{
throw exp;
}
finally
{
xr.Close();
}
}
使用BinaryFormatter 序列化
使用Binary序列化后,通常会把把它存贮在文件中,但如果把序列化的对象放到页面上进行传值或者是放在特定格式的文件里时,通常会搞得一团糟。所以我选择把对象序列化后,并用0-F之间的字母表示 ,尽管这样它的体积会增大4倍,但我个人认为是物超所值的。
public string WriteToBinary<T>(T instance)
{
BinaryFormatter binFmater = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
binFmater.Serialize(ms, instance);
ms.Position = 0;
byte[] btArray = ms.ToArray();
StringBuilder strBuilder = new StringBuilder();
foreach (byte bt in btArray)
{
strBuilder.Append(string.Format("{0:X2}", bt));
}
return strBuilder.ToString();
}
}
public T ReadFromBinary<T>(string str)
{
int ilenght = str.Length / 2;
byte[] btArray = new byte[ilenght];
for (int i = 0; i < ilenght; i++)
{
int ibyte = Convert.ToInt32(str.Substring(i * 2, 2), 16);
btArray[i] = (byte)ibyte;
}
BinaryFormatter binFmater = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(btArray))
{
T instance = (T)binFmater.Deserialize(ms);
return instance;
}
}
使用SoapFormatter 序列化
很多人也喜欢用SOAP对对象进行序列化,但要注意一点在Framework 1.1.4版本的Soap与Framework2.0/3.0/3.5 的不兼容。这个也是我头痛的事。这让我在使用区域集成服务器同步数据的时候差点疯了。有一部分程序是升级到了.NET 2.0,又有一部分程序还是.NET 1.1.4版的,两者不兼容,无奈之下,只能在2.0里嵌入VS2003编写的exe程序。或许这就是微软给我们开的一个玩笑吧!
在使用Soap进行序列华时,需要引用对System.Runtime.Serialization.Formatters.Soap.dll进行引用。
public string WriteToSoap<T>(T instance)
{
SoapFormatter SoapFmater = new SoapFormatter();
using (MemoryStream ms = new MemoryStream())
{
SoapFmater.Serialize(ms, instance);
ms.Position = 0;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ms);
return xmlDoc.InnerXml;
}
}
public T ReadFromSoap<T>(string str)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(str);
SoapFormatter SoapFmater = new SoapFormatter();
using (MemoryStream ms = new MemoryStream())
{
xmlDoc.Save(ms);
ms.Position = 0;
T instance = (T)SoapFmater.Deserialize(ms);
return instance;
}
}
SOAP序列化的一个优势
使用Soap序列化的对象,包含类的描述非常详细,反序列化时对类型要求不是非常严格,不会受继承的影响。看一下例子就可以明白的理解了。
public class A
{
///…
}
public class B : A
{
///…
}
在主程序中使用时,Xml与Binary对类型的要求方面非常严格,但Soap却可以游刃有余。
public void Process()
{
Common.Serialization.SerializeHelper shelper = new Common.Serialization.SerializeHelper();
B b = new B();
A a = new A();
string strSoap = shelper.WriteToSoap<B>(b);
A a_Soap = shelper.ReadFromSoap<A>(strSoap);//正确
string strXml = shelper.WriteToXml<B>(b);
A a_Xml = shelper.ReadFromXml<A>(strXml);//错误
string strBinary = shelper.WriteToBinary<B>(b);
A a_Binary = shelper.ReadFromBinary<A>(b);//错误
}
在对象传输中,一般都会选择使用Soap进行传输,因为我们只约定好接口,传递过来的数据就可以被反序列化后正常调用。