zl程序教程

您现在的位置是:首页 >  后端

当前栏目

c#序列化详解示例

c# 详解 示例 序列化
2023-06-13 09:15:17 时间


几种序列化技术:
1)二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。远程处理使用序列化“通过值”在计算机或应用程序域之间传递对象。
2)XML序列化仅序列化公共属性和字段,且不保持类型保真度。当您要提供或使用数据而不限制使用该数据的应用程序时,这一点是很有用的。由于XML是一个开放式标准,因此,对于通过Web共享数据而言,这是一个很好的选择。SOAP同样是一个开放式标准,这使它也成为一个颇具吸引力的选择。
3)使用提供的数据协定,将类型实例序列化和反序列化为XML流或文档(或者JSON格式)。常应用于WCF通信。

BinaryFormatter

序列化可被定义为将对象的状态存储到存储媒介中的过程。在此过程中,对象的公共字段和私有字段以及类的名称(包括包含该类的程序集)都被转换为字节流,然后写入数据流。在以后反序列化该对象时,创建原始对象的精确复本。

1、使一个类可序列化的最简单方式是按如下所示使用Serializable属性标记。

2、有选择的序列化

通过用NonSerialized属性标记成员变量,可以防止它们被序列化

3、自定义序列化

1)在序列化期间和之后运行自定义方法
最佳做法也是最简单的方法(在.NetFramework2.0版中引入),就是在序列化期间和之后将下列属性应用于用于更正数据的方法:

复制代码代码如下:


OnDeserializedAttribute
OnDeserializingAttribute
OnSerializedAttribute
OnSerializingAttribute

具体事例如下:

复制代码代码如下:


//Thisistheobjectthatwillbeserializedanddeserialized.
[Serializable()] 
publicclassTestSimpleObject 
{
   //Thismemberisserializedanddeserializedwithnochange.
   publicintmember1;

   //Thevalueofthisfieldissetandresetduringand
   //afterserialization.
   privatestringmember2;

   //Thisfieldisnotserialized.TheOnDeserializedAttribute
   //isusedtosetthemembervalueafterserialization.
   [NonSerialized()]
   publicstringmember3;

   //Thisfieldissettonull,butpopulatedafterdeserialization.
   privatestringmember4;

   //Constructorfortheclass.
   publicTestSimpleObject()
   {
 member1=11;
 member2="HelloWorld!";
 member3="Thisisanonserializedvalue";
 member4=null;
   }

   publicvoidPrint()
   {
 Console.WriteLine("member1="{0}"",member1);
 Console.WriteLine("member2="{0}"",member2);
 Console.WriteLine("member3="{0}"",member3);
 Console.WriteLine("member4="{0}"",member4);
   }

   [OnSerializing()]
   internalvoidOnSerializingMethod(StreamingContextcontext)
   {
 member2="Thisvaluewentintothedatafileduringserialization.";
   }

   [OnSerialized()]
   internalvoidOnSerializedMethod(StreamingContextcontext)
   {
 member2="Thisvaluewasresetafterserialization.";
   }

   [OnDeserializing()]
   internalvoidOnDeserializingMethod(StreamingContextcontext)
   {
 member3="Thisvaluewassetduringdeserialization";
   }

   [OnDeserialized()]
   internalvoidOnDeserializedMethod(StreamingContextcontext)
   {
 member4="Thisvaluewassetafterdeserialization.";
   }   
}

2)实现ISerializable接口

对于用Serializable属性标记且在类级别上或其构造函数上具有声明性或命令性安全的类,不应使用默认序列化。相反,这些类应始终实现ISerializable接口。实现ISerializable涉及实现GetObjectData方法以及在反序列化对象时使用的特殊构造函数。

具体实例如下:

复制代码代码如下:
[Serializable]
publicclassMyObject:ISerializable
{
 publicintn1;
 publicintn2;
 publicStringstr;

 publicMyObject()
 {
 }

 protectedMyObject(SerializationInfoinfo,StreamingContextcontext)
 {
   n1=info.GetInt32("i");
   n2=info.GetInt32("j");
   str=info.GetString("k");
 }
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter
=true)]
 publicvirtualvoidGetObjectData(SerializationInfoinfo,StreamingContextcontext)
 {
   info.AddValue("i",n1);
   info.AddValue("j",n2);
   info.AddValue("k",str);
 }
}

注意:

在反序列化一个对象时不调用构造函数。出于性能方面的原因对反序列化施加了该约束。但是,这违反了运行库与对象编写器之间的一些通常约定,开发人员应确保他们在将对象标记为可序列化时了解其后果。

SoapFormatter

 以SOAP格式将对象或整个连接对象的图形序列化和反序列化。基本用法类似于BinaryFormatter。SoapFormatter和BinaryFormatter两个类实现IRemotingFormatter接口以支持远程过程调用(RPC),实现IFormatter接口(由IRemotingFormatter继承)以支持对象图形的序列化。SoapFormatter类还支持对ISoapMessage对象进行RPC,而不必使用IRemotingFormatter功能。

XmlSerializer

将对象序列化到XML文档中和从XML文档中反序列化对象。XmlSerializer使您得以控制如何将对象编码到XML中。

XML序列化是将对象的公共属性(Property)和字段转换为序列格式(这里是指XML)以便存储或传输的过程。反序列化则是从XML输出中重新创建原始状态的对象。因此,可以将序列化视为将对象的状态保存到流或缓冲区的方法。例如,ASP.NET使用XmlSerializer类对XMLWebservices消息进行编码。

例子:

C#代码

复制代码代码如下:
publicclassMyClass
{
   publicMyObjectMyObjectProperty;
}
publicclassMyObject
{
   publicstringObjectName;
}

序列化后的XML  

复制代码代码如下:
<MyClass>
 <MyObjectProperty>
 <ObjectName>MyString</ObjectName>
 </MyObjectProperty>
</MyClass>

还可以通过标记来控制XML的输出

1、默认值

DefaultValueAttribute

2、过滤某属性或字段

 XmlIgnoreAttribute

3、重写默认序列化逻辑
4、将对象序列化为SOAP编码的XML流

注意

XML序列化不转换方法、索引器、私有字段或只读属性(只读集合除外)。要序列化对象的所有字段和属性(公共的和私有的),请使用BinaryFormatter,而不要使用XML序列化。

DataContractSerializer

使用提供的数据协定,将类型实例序列化和反序列化为XML流或文档。此类不能被继承。

DataContractSerializer用于序列化和反序列化在WindowsCommunicationFoundation(WCF)消息中发送的数据。通过将DataContractAttribute属性(Attribute)应用于类,而将DataMemberAttribute属性(Attribute)应用于类成员,可以指定要序列化的属性(Property)和字段。

使用步骤:

1)DataContractSerializer与DataContractAttribute和DataMemberAttribute类结合使用。

要准备序列化某个类,请将DataContractAttribute应用于该类。对于返回要序列化的数据的类的每个成员,请应用DataMemberAttribute。您可以序列化字段和属性,而无论其可访问性级别是什么:private、protected、internal、protectedinternal或public。

2)添加到已知类型的集合中

在序列化或反序列化对象时,DataContractSerializer必须“已知”该类型。首先,创建一个实现IEnumerable<T>(如List<T>)的类实例,并将已知类型添加到集合中。然后,使用接受IEnumerable<T>(例如,[M:System.Runtime.Serialization.DataContractSerializer.#ctor(System.Type,System.Collections.Generic.IEnumerable{System.Type}])的重载之一创建DataContractSerializer的实例。

具体实例:

复制代码代码如下:
namespaceDataContractSerializerExample
{
   usingSystem;
   usingSystem.Collections;
   usingSystem.Collections.Generic;
   usingSystem.Runtime.Serialization;
   usingSystem.Xml;

   //YoumustapplyaDataContractAttributeorSerializableAttribute
   //toaclasstohaveitserializedbytheDataContractSerializer.
   [DataContract(Name="Customer",Namespace="http://www.contoso.com")]
   classPerson:IExtensibleDataObject
   {
 [DataMember()]
 publicstringFirstName;
 [DataMember]
 publicstringLastName;
 [DataMember()]
 publicintID;

 publicPerson(stringnewfName,stringnewLName,intnewID)
 {
FirstName=newfName;
LastName=newLName;
ID=newID;
 }

 privateExtensionDataObjectextensionData_Value;

 publicExtensionDataObjectExtensionData
 {
get
{
   returnextensionData_Value;
}
set
{
   extensionData_Value=value;
}
 }
   }

   publicsealedclassTest
   {
 privateTest(){}

 publicstaticvoidMain()
 {
try
{
   WriteObject("DataContractSerializerExample.xml");
   ReadObject("DataContractSerializerExample.xml");

}

catch(SerializationExceptionserExc)
{
   Console.WriteLine("SerializationFailed");
   Console.WriteLine(serExc.Message);
}
catch(Exceptionexc)
{
   Console.WriteLine(
   "Theserializationoperationfailed:{0}StackTrace:{1}",
   exc.Message,exc.StackTrace);
}

finally
{
   Console.WriteLine("Press<Enter>toexit....");
   Console.ReadLine();
}
 }

 publicstaticvoidWriteObject(stringfileName)
 {
Console.WriteLine(
   "CreatingaPersonobjectandserializingit.");
Personp1=newPerson("Zighetti","Barbara",101);
FileStreamwriter=newFileStream(fileName,FileMode.Create);
DataContractSerializerser=
   newDataContractSerializer(typeof(Person));
ser.WriteObject(writer,p1);
writer.Close();
 }

 publicstaticvoidReadObject(stringfileName)
 {
Console.WriteLine("Deserializinganinstanceoftheobject.");
FileStreamfs=newFileStream(fileName,
FileMode.Open);
XmlDictionaryReaderreader=
   XmlDictionaryReader.CreateTextReader(fs,newXmlDictionaryReaderQuotas());
DataContractSerializerser=newDataContractSerializer(typeof(Person));

//Deserializethedataandreaditfromtheinstance.
PersondeserializedPerson=
   (Person)ser.ReadObject(reader,true);
reader.Close();
fs.Close();
Console.WriteLine(String.Format("{0}{1},ID:{2}",
deserializedPerson.FirstName,deserializedPerson.LastName,
deserializedPerson.ID));
 }
   }

DataContractJsonSerializer

将对象序列化为JavaScript对象表示法(JSON),并将JSON数据反序列化为对象。此类不能被继承。

具体使用与DataContractSerializer类似。这里不再赘述。

下面对这些方法的使用做了汇总,希望能给大家带来一些帮助。

复制代码代码如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.IO;
usingSystem.Runtime.Serialization;
usingSystem.Runtime.Serialization.Json;
usingSystem.Runtime.Serialization.Formatters.Binary;
usingSystem.Runtime.Serialization.Formatters.Soap;
usingSystem.Xml.Serialization;

namespaceSerializerSample
{
   ///<summary>
   ///序列化帮助类
   ///</summary>
   publicsealedclassSerializeHelper
   {
 #regionDataContract序列化
 ///<summary>
 ///DataContract序列化
 ///</summary>
 ///<paramname="value"></param>
 ///<paramname="knownTypes"></param>
 ///<returns></returns>
 publicstaticstringSerializeDataContract(objectvalue,List<Type>knownTypes=null)
 {
DataContractSerializerdataContractSerializer=newDataContractSerializer(value.GetType(),knownTypes);

using(MemoryStreamms=newMemoryStream())
{
   dataContractSerializer.WriteObject(ms,value);
   ms.Seek(0,SeekOrigin.Begin);
   using(StreamReadersr=newStreamReader(ms))
   {
 returnsr.ReadToEnd();
   }
}
 }
 ///<summary>
 ///DataContract反序列化
 ///</summary>
 ///<typeparamname="T"></typeparam>
 ///<paramname="xml"></param>
 ///<returns></returns>
 publicstaticTDeserializeDataContract<T>(stringxml)
 {
using(MemoryStreamms=newMemoryStream(Encoding.UTF8.GetBytes(xml)))
{
   DataContractSerializerserializer=newDataContractSerializer(typeof(T));
   return(T)serializer.ReadObject(ms);
}
 }
 #endregion

 #regionDataContractJson序列化
 ///<summary>
 /// DataContractJson序列化
 ///</summary>
 ///<paramname="value"></param>
 ///<returns></returns>
 publicstaticstringSerializeDataContractJson(objectvalue)
 {
DataContractJsonSerializerdataContractSerializer=newDataContractJsonSerializer(value.GetType());
using(MemoryStreamms=newMemoryStream())
{   
   dataContractSerializer.WriteObject(ms,value);
   returnEncoding.UTF8.GetString(ms.ToArray());
}
 }
 ///<summary>
 /// DataContractJson反序列化
 ///</summary>
 ///<paramname="type"></param>
 ///<paramname="str"></param>
 ///<returns></returns>
 publicstaticobjectDeserializeDataContractJson(Typetype,stringstr)
 {
DataContractJsonSerializerdataContractSerializer=newDataContractJsonSerializer(type);
using(MemoryStreamms=newMemoryStream(System.Text.Encoding.UTF8.GetBytes(str)))
{
   returndataContractSerializer.ReadObject(ms);
}
 }
 ///<summary>
 ///DataContractJson反序列化
 ///</summary>
 ///<typeparamname="T"></typeparam>
 ///<paramname="json"></param>
 ///<returns></returns>
 publicTDeserializeDataContractJson<T>(stringjson)
 {
DataContractJsonSerializerdataContractSerializer=newDataContractJsonSerializer(typeof(T));
using(MemoryStreamms=newMemoryStream(Encoding.UTF8.GetBytes(json)))
{
   return(T)dataContractSerializer.ReadObject(ms);
}
 }
 #endregion

 #regionXmlSerializer序列化
 ///<summary>
 ///将对象序列化到XML文档中和从XML文档中反序列化对象。XmlSerializer使您得以控制如何将对象编码到XML中。
 ///</summary>
 ///<paramname="value"></param>
 ///<returns></returns>
 publicstaticstringSerializeXml(objectvalue)
 {
XmlSerializerserializer=newXmlSerializer(value.GetType());
using(MemoryStreamms=newMemoryStream())
{
   serializer.Serialize(ms,value);
   ms.Seek(0,SeekOrigin.Begin);
   using(StreamReadersr=newStreamReader(ms))
   {
 returnsr.ReadToEnd();
   }
}
 }
 ///<summary>
 /// XmlSerializer反序列化
 ///</summary>
 ///<paramname="type"></param>
 ///<paramname="str"></param>
 ///<returns></returns>
 publicstaticobjectDeserializeXml(Typetype,stringstr)
 {
XmlSerializerserializer=newXmlSerializer(type);
byte[]bytes=System.Text.Encoding.UTF8.GetBytes(str);
using(MemoryStreamms=newMemoryStream(bytes))
{
   returnserializer.Deserialize(ms);
}
 }
 #endregion

 #regionBinaryFormatter序列化
 ///<summary>
 ///BinaryFormatter序列化
 ///必须类型必须标记为Serializable
 ///</summary>
 ///<paramname="obj"></param>
 ///<returns></returns>
 publicstaticstringSerializeBinaryFormatter(objectobj)
 {
BinaryFormatterformatter=newBinaryFormatter();
using(MemoryStreamms=newMemoryStream())
{
   formatter.Serialize(ms,obj);
   byte[]bytes=ms.ToArray();
   obj=formatter.Deserialize(newMemoryStream(bytes));
   //如果是UTF8格式,则反序列化报错。可以用Default格式,不过,建议还是传参为byte数组比较好
   returnEncoding.Default.GetString(bytes);
}
 }

 ///<summary>
 ///BinaryFormatter反序列化
 ///必须类型必须标记为Serializable
 ///</summary>
 ///<paramname="serializedStr"></param>
 ///<returns></returns>
 publicstaticTDeserializeBinaryFormatter<T>(stringserializedStr)
 {
BinaryFormatterformatter=newBinaryFormatter();
byte[]bytes=Encoding.Default.GetBytes(serializedStr);
using(MemoryStreamms=newMemoryStream(bytes))
{
   return(T)formatter.Deserialize(ms);
}
 }
 #endregion

 #regionSoapFormatter序列化
 ///<summary>
 ///SoapFormatter序列化
 ///必须类型必须标记为Serializable
 ///</summary>
 ///<paramname="obj"></param>
 ///<returns></returns>
 publicstaticstringSerializeSoapFormatter(objectobj)
 {
SoapFormatterformatter=newSoapFormatter();
using(MemoryStreamms=newMemoryStream())
{
   formatter.Serialize(ms,obj);
   byte[]bytes=ms.ToArray();
   returnEncoding.UTF8.GetString(bytes);
}
 }
 ///<summary>
 ///SoapFormatter反序列化
 ///必须类型必须标记为Serializable
 ///</summary>
 ///<paramname="serializedStr"></param>
 ///<returns></returns>
 publicstaticTDeserializeSoapFormatter<T>(stringserializedStr)
 {
SoapFormatterformatter=newSoapFormatter();
using(MemoryStreamms=newMemoryStream(Encoding.UTF8.GetBytes(serializedStr)))
{
   return(T)formatter.Deserialize(ms);
}
 }
 #endregion
   }
}