根据序列化的格式,序列化分为以下三种形式:
二进制序列化
指对象序列化之后是二进制形式的。通过 BinaryFormatter
类实现,这个类位于 System.Runtime.Serialization.Formatters.Binary
命名空间下。BinaryFormatter
效率很高,能生成非常紧凑的字节流。
所有成员,甚至只读成员都被执行序列化与反序列化
XML序列化
指对象序列化之后的结果是XML形式的。通过 XmlSerializer
类实现,这个类位于 System.Xml.Serialization
命名空间下。XML序列化仅将对象的公共字段和属性
序列化为XML流,XML序列化不包括类型信息
。
SOAP序列化
指对象序列化之后的结果符合SOAP协议,也就是说可以通过SOAP协议传输。通过SoapFormatter
类实现,这个类位于System.Runtime.Serialization.Formatters.Soap
命名空间下。
对序列化进行分类的另一种方式是基于序列化的深度
。基于序列化的深度序列化可分为两种形式:
深序列化
序列化类的所有public
,protected
和private
成员。甚至嵌套类和它们public
、protected
和private
成员也被序列化。
浅序列化
.NET框架中,使用二进制格式序列化类的对象,采用深序列化,而使用XML格式序列化类对象为浅序列化。
[Serializable] // 二进制序列化需要以此特性进行标记
public class Person
{
[NonSerialized] // 表示该字段不参与序列化
private string id = "1234567890";
public string Sno { get; set; }
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
public string DisplayInfo()
{
return $"我的学号是:{Sno}\n我的名字是: {Name}\n我的性别为:{Sex}\n我的年龄:{Age}\n我的ID: {id}";
}
}
class Program
{
static void Main(string[] args)
{
var me = new Person
{
Sno = "200719",
Name = "yuananyun",
Sex = "man",
Age = 22
};
// BinaryFormatter 序列化方式
using (Stream stream = new FileStream("personInfoBinary.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, me);
}
// BinaryFormatter 反序列化方式
using (Stream destream = new FileStream("personInfoBinary.txt", FileMode.Open, FileAccess.Read, FileShare.Read))
{
IFormatter formatter = new BinaryFormatter();
var stillme = (Person)formatter.Deserialize(destream);
Console.WriteLine(stillme.DisplayInfo());
}
Console.ReadKey();
}
}
[Serializable]
public class TestSimpleObject : System.Runtime.Serialization.ISerializable
{
public int member1;
private string member2;
[NonSerialized()]
public string member3;
private string member4;
public TestSimpleObject()
{
member1 = 11;
member2 = "Hello World!";
member3 = "This is a nonserialized value";
member4 = null;
}
protected TestSimpleObject(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
Console.WriteLine();
Console.WriteLine("==================================");
Print();
member1 = info.GetInt32(nameof(member1)) + 1;
member2 = info.GetString(nameof(member2)) + " 8888";
member3 = info.GetString(nameof(member3)) + " 8888";
member4 = info.GetString(nameof(member4)) + " 8888";
Console.WriteLine();
Console.WriteLine(nameof(TestSimpleObject));
Print();
}
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
Console.WriteLine();
Console.WriteLine("==================================");
Print();
info.AddValue(nameof(member1), member1 - 1);
info.AddValue(nameof(member2), member2 + " 0000");
info.AddValue(nameof(member3), member3 + " 0000");
info.AddValue(nameof(member4), member4 + " 0000");
}
public void Print()
{
Console.WriteLine("member1 = '{0}'", member1);
Console.WriteLine("member2 = '{0}'", member2);
Console.WriteLine("member3 = '{0}'", member3);
Console.WriteLine("member4 = '{0}'", member4);
}
[System.Runtime.Serialization.OnSerializing()]
internal void OnSerializingMethod(System.Runtime.Serialization.StreamingContext context)
{
Console.WriteLine();
Console.WriteLine("==================================");
Print();
member2 = "This value went into the data file during serialization.";
Console.WriteLine();
Console.WriteLine(nameof(OnSerializingMethod));
Print();
}
[System.Runtime.Serialization.OnSerialized()]
internal void OnSerializedMethod(System.Runtime.Serialization.StreamingContext context)
{
Console.WriteLine();
Console.WriteLine("==================================");
Print();
member2 = "This value was reset after serialization.";
Console.WriteLine();
Console.WriteLine(nameof(OnSerializedMethod));
Print();
}
[System.Runtime.Serialization.OnDeserializing()]
internal void OnDeserializingMethod(System.Runtime.Serialization.StreamingContext context)
{
Console.WriteLine();
Console.WriteLine("==================================");
Console.WriteLine(nameof(OnDeserializingMethod));
Print();
Console.WriteLine();
member3 = "This value was set during deserialization";
Print();
}
[System.Runtime.Serialization.OnDeserialized()]
internal void OnDeserializedMethod(System.Runtime.Serialization.StreamingContext context)
{
Console.WriteLine();
Console.WriteLine("==================================");
Console.WriteLine(nameof(OnDeserializedMethod));
Print();
Console.WriteLine();
member1 = member1 + 10000;
member4 = "This value was set after deserialization.";
Print();
}
}
class Program
{
static void Main(string[] args)
{
try
{
using (Stream stream = File.Open("DataFile.dat", FileMode.Create))
{
TestSimpleObject obj = new TestSimpleObject();
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formatter.Serialize(stream, obj);
}
using (Stream stream = File.Open("DataFile.dat", FileMode.Open))
{
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
var obj = (TestSimpleObject)formatter.Deserialize(stream);
}
}
catch (System.Runtime.Serialization.SerializationException se)
{
Console.WriteLine("Failed to serialize. Reason: " + se.Message);
}
catch (Exception exc)
{
Console.WriteLine("An exception occurred. Reason: " + exc.Message);
}
}
}
==================================
member1 = ‘11’
member2 = ‘Hello World!’
member3 = ‘This is a nonserialized value’
member4 = ‘’OnSerializingMethod
member1 = ‘11’
member2 = ‘This value went into the data file during serialization.’
member3 = ‘This is a nonserialized value’
member4 = ‘’==================================
member1 = ‘11’
member2 = ‘This value went into the data file during serialization.’
member3 = ‘This is a nonserialized value’
member4 = ‘’==================================
member1 = ‘11’
member2 = ‘This value went into the data file during serialization.’
member3 = ‘This is a nonserialized value’
member4 = ‘’OnSerializedMethod
member1 = ‘11’
member2 = ‘This value was reset after serialization.’
member3 = ‘This is a nonserialized value’
member4 = ‘’==================================
OnDeserializingMethod
member1 = ‘0’
member2 = ‘’
member3 = ‘’
member4 = ‘’member1 = ‘0’
member2 = ‘’
member3 = ‘This value was set during deserialization’
member4 = ‘’==================================
member1 = ‘0’
member2 = ‘’
member3 = ‘This value was set during deserialization’
member4 = ‘’TestSimpleObject
member1 = ‘11’
member2 = ‘This value went into the data file during serialization. 0000 8888’
member3 = ‘This is a nonserialized value 0000 8888’
member4 = ’ 0000 8888’==================================
OnDeserializedMethod
member1 = ‘11’
member2 = ‘This value went into the data file during serialization. 0000 8888’
member3 = ‘This is a nonserialized value 0000 8888’
member4 = ’ 0000 8888’member1 = ‘10011’
member2 = ‘This value went into the data file during serialization. 0000 8888’
member3 = ‘This is a nonserialized value 0000 8888’
member4 = ‘This value was set after deserialization.’
XML序列化时使用XmlSerializer
类所带来的好处如下:
指定将字段或属性编码为特性
还是元素
指定要使用XML命名空间
。
如果字段或属性不合适,则指定元素或属性的名称。
XML 序列化时使用XmlSerializer
类应考虑下列情况。
序列化数据只包含数据本身以及类的结构,不包括类型标识和程序集信息。
只能序列化公共属性和字段
。如果需要序列化非公共数据,请使用BinaryFormatter
类而不是XML序列化。
类必须有一个默认构造函数。
不能序列化方法。
进行序列化的类的名称作为XML的根元素,公共字段或属性作为XML根元素的子元素。
public class Customer
{
private int _mID;
private string _mfirstname;
private string _mlastname;
private string _mphone;
private string _mnotes;
public int CustomerID
{
get { return _mID; }
set { _mID = value; }
}
public string FirstName
{
get { return _mfirstname; }
set { _mfirstname = value; }
}
public string LastName
{
get { return _mlastname; }
set { _mlastname = value; }
}
public string HomePhone
{
get { return _mphone; }
set { _mphone = value; }
}
public string Notes
{
get { return _mnotes; }
set { _mnotes = value; }
}
}
class Program
{
static void Main(string[] args)
{
var custom = new Customer()
{
CustomerID = 1234,
FirstName = "Steven",
LastName = "Zhou",
HomePhone = "1234567890",
Notes = "Test"
};
{
FileStream stream = new FileStream("Customer.xml", FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
serializer.Serialize(stream, custom);
stream.Close();
}
// 使用浏览器打开
Process.Start(System.AppDomain.CurrentDomain.BaseDirectory + "Customer.xml");
{
Customer cus;
FileStream stream = new FileStream("Customer.xml", FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
cus = (Customer)serializer.Deserialize(stream);
stream.Close();
}
Console.ReadKey();
}
}
<?xml version="1.0"?>
<Customer xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CustomerID>1234</CustomerID>
<FirstName>Steven</FirstName>
<LastName>Zhou</LastName>
<HomePhone>1234567890</HomePhone>
<Notes>Test</Notes>
</Customer>
名称 | 说明 |
---|---|
UnknownAttribute | 当XmlSerializer 在反序列化过程中遇到未知类型的XML属性(Attribute)时发生 |
UnknownElement | 当XmlSerializer 在反序列化过程中遇到未知类型的XML元素时发生 |
UnknownNode | 当XmlSerializer 在反序列化过程中遇到未知类型的XML节点时发生 |
UnreferencedObject | 在反序列化SOAP编码的XML流的过程中发生,此时XmlSerializer 遇到未使用(或未引用)的识别类型 |
class Program
{
static void Main(string[] args)
{
var custom = new Customer()
{
CustomerID = 1234,
FirstName = "Steven",
LastName = "Zhou",
HomePhone = "1234567890",
Notes = "Test"
};
{
FileStream stream = new FileStream("Customer.xml", FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
serializer.Serialize(stream, custom);
stream.Close();
}
Process.Start(System.AppDomain.CurrentDomain.BaseDirectory + "Customer.xml");
{
Customer cus;
FileStream stream = new FileStream("Customer.xml", FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
serializer.UnknownAttribute += new XmlAttributeEventHandler(serializer_UnknownAttribute);
serializer.UnknownElement += new XmlElementEventHandler(serializer_UnknownElement);
serializer.UnknownNode += new XmlNodeEventHandler(serializer_UnknownNode);
cus = (Customer)serializer.Deserialize(stream);
stream.Close();
}
Console.ReadKey();
}
private static void serializer_UnknownNode(object sender, XmlNodeEventArgs e)
{
Debug.WriteLine("Unknown Node " + e.Name + " found at Line " + e.LineNumber);
}
private static void serializer_UnknownElement(object sender, XmlElementEventArgs e)
{
Debug.WriteLine("Unknown Element " + e.Element.Name + " found at Line " + e.LineNumber);
}
private static void serializer_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
Debug.WriteLine("Unknown Attribute " + e.Attr.Name + " found at Line " + e.LineNumber);
}
}
对于复杂类型或嵌套类型:
XmlSerializer
实例化主类,以及所有子类,并分配到各自的属性中。XmlSerializer
创建一个与序列化元素的数目具有相同数目的数组,然后指定相应的数组元素值。XmlSerializer
类在序列化对象时自动将公有成员
的名称作为生成的XML元素名称。在许多情况下这是符合我们需要的。然而,有时你可能需要自定义序列化的XML数据,以满足需求。
System.Xml.Serialization
命名空间提供了一些属性类来帮助完成上述的自定义序列化。
名称 | 描述 |
---|---|
XmlAttributes | 表示一个特性对象的集合,这些对象控制XmlSerializer 如何序列化和反序列化对象 |
XmlArrayAttribute | 指定XmlSerializer 应将特定的类成员序列化为XML元素数组 |
XmlArrayItemAttribute | 指定XmlSerializer 可以放置在序列化数组中的派生类型 |
XmlArrayItemAttributes | 表示XmlArrayItemAttribute 对象的集合 |
XmlAttributeAttribute | 指定XmlSerializer 应将类成员作为XML属性进行序列化 |
XmlChoiceIdentifierAttribute | 指定可以通过使用枚举类进一步消除成员的歧义 |
XmlElementAttribute | 在XmlSerializer 序列化或反序列化包含对象时,指示公共字段或属性标识XML元素 |
XmlElementAttributes | 标识XmlElementAttribute 的集合,XmlSerializer 将其用于它重写序列化类的默认方式 |
XmlEnumAttribute | 控制XmlSerializer 如何序列化枚举成员 |
XmlIgnoreAttribute | 指示XmlSerializer 的Serializer 方法不序列化公共字段或公共属性 |
XmlIncludeAttribute | 允许XmlSerializer 在它序列化或反序列化对象时识别类型 |
XmlRootAttribute | 控制视为XML根元素的属性目标的XML序列化 |
XmlTextAttribute | 当序列化或反序列化包含类时,向XmlSerializer 指示应将此成员作为XML文本处理 |
XmlTypeAttribute | 控制当属性目标由XmlSerializer 序列化时生成的XML架构 |
XmlAnyAttibuteAttribute | 指定成员(返回XmlAttribute 对象的数组的字段)可以包含任何XML属性 |
XmlAnyElelementAttribute | 指定成员(返回XmlElement 或XmlNode 对象的数组的字段)可以包含对象,该对象标识在序列化或反序列化的对象中没有相应成员的所有XML元素 |
XmlAnyElelementAttributes | 表示XmlAnyElelementAttribute 对象的集合 |
XmlAttributeEventArgs | 为UnknownAttribute 事件提供数据 |
XmlAttributeOverrides | 允许你在使用XmlSerializer 序列化或反序列化对象时重写属性、字段和类特性 |
XmlElementEventArgs | 为UnknownElement 事件提供数据 |
XmlNamespaceDeclarationsAttribte | 指定目标属性、参数、返回值或类成员包含于XML文档中所用的命名空间关联的前缀 |
XmlSerializer | 将对象序列化到XML文档中和从XML文档中反序列化对象。XmlSerialzier 使你得以控制如何将对象编码到XML中 |
XmlSerilizerNamespaces | 包含XmlSerializer 用于在XM文档实例中生成限定名的XML命名空间和前缀 |
XmlTypeMapping | 包含从一种类型到另一种类型的映射 |
public enum CustomerType
{
[XmlEnumAttribute(Name="Personal Customer")]
Personal,
[XmlEnumAttribute(Name="Company Customer")]
Company
}
public class Address
{
private string _mstreet;
private string _mcity;
private string _mstate;
private string _mcountry;
private string _mpostalcode;
public string Street
{
get { return _mstreet; }
set { _mstreet = value; }
}
public string City
{
get { return _mcity; }
set { _mcity = value; }
}
public string State
{
get { return _mstate; }
set { _mstate = value; }
}
public string Country
{
get { return _mcountry; }
set { _mcountry = value; }
}
public string PostalCode
{
get { return _mpostalcode; }
set { _mpostalcode = value; }
}
}
class Program
{
static void Main(string[] args)
{
var custom = new Customer()
{
CustomerID = 1234,
FirstName = "Steven",
LastName = "Zhou",
HomePhone = "1234567890",
Notes = "Test",
Emails = new string[]
{
"abc@gmail.com",
"bcd@gmail.com",
"cde@gmail.com",
"def@gmail.com"
},
Type = CustomerType.Company
};
{
FileStream stream = new FileStream("Customer.xml", FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
serializer.Serialize(stream, custom);
stream.Close();
}
Process.Start(System.AppDomain.CurrentDomain.BaseDirectory + "Customer.xml");
{
Customer cus;
FileStream stream = new FileStream("Customer.xml", FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
cus = (Customer)serializer.Deserialize(stream);
stream.Close();
}
Console.ReadKey();
}
}
// 改变XML文档的根元素名
[XmlRootAttribute(ElementName="CustomerInfo")]
public class Customer
{
private int _mID;
private string _mfirstname;
private string _mlastname;
private string _mphone;
private string _mnotes;
private string[] _memails;
private CustomerType _mtype;
private Address _maddress = new Address();
// 表示将把类的共有属性序列化为XML属性,而不是XML元素
[XmlAttributeAttribute(AttributeName="CustomerID")]
public int CustomerID
{
get { return _mID; }
set { _mID = value; }
}
[XmlElementAttribute(ElementName="FName")]
public string FirstName
{
get { return _mfirstname; }
set { _mfirstname = value; }
}
[XmlElementAttribute(ElementName = "LName")]
public string LastName
{
get { return _mlastname; }
set { _mlastname = value; }
}
// 忽略该公开属性的序列化
[XmlIgnoreAttribute]
public string HomePhone
{
get { return _mphone; }
set { _mphone = value; }
}
[XmlElementAttribute(ElementName = "Remarks")]
public string Notes
{
get { return _mnotes; }
set { _mnotes = value; }
}
[XmlElementAttribute(ElementName = "CustomerType")]
public CustomerType Type
{
get { return _mtype; }
set { _mtype = value; }
}
// 指定序列化数组时,元素的名称,元素项的名称
[XmlArrayAttribute(ElementName="EmailAddresses")]
[XmlArrayItemAttribute(ElementName="Email")]
public string[] Emails
{
get { return _memails; }
set { _memails = value; }
}
// 如果该属性为null,XmlAttribte仍然为它设置一个空XML元素
[XmlElementAttribute(IsNullable=true)]
public Address Address
{
get { return _maddress; }
set { _maddress = value; }
}
}
<?xml version="1.0"?>
<CustomerInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
CustomerID="1234">
<FName>Steven</FName>
<LName>Zhou</LName>
<Remarks>Test</Remarks>
<CustomerType>Company Customer</CustomerType>
<EmailAddresses>
<Email>abc@gmail.com</Email>
<Email>bcd@gmail.com</Email>
<Email>cde@gmail.com</Email>
<Email>def@gmail.com</Email>
</EmailAddresses>
<Address />
</CustomerInfo>
/// <summary>
/// 指定邮件地址的类型
/// </summary>
public enum EmailDestination
{
Home = 0,
Business = 1,
Other = 2,
}
//表明该类能被序列化
[Serializable]
public class EmailAddress
{
public EmailAddress()
{
}
[XmlAttributeAttribute] // 指名这个公有字段被序列化时,将作为XML的属性出现
public string Address = null;
[XmlAttributeAttribute] // 指名这个公有字段被序列化时,将作为XML的属性出现
public EmailDestination Destination = EmailDestination.Home;
}
//设置'Customer'作为任何序列化的XML文档的根元素名
[XmlRootAttribute("Customer", Namespace = "", IsNullable = false)]
public class Customer
{
#region Variables
private Bitmap picture;
[XmlAttributeAttribute(DataType="date")] //指名这个公有字段被序列化时,作为根节点的属性出现
public System.DateTime DateTimeValue;
public int CustomerID;
public string CustomerName;
public int Age;
[XmlIgnoreAttribute()] //序列化时忽略这个字段
public bool CustomerPaid;
//序列化名为'Hobbies'的ArrayList数组,并将'Hobby'作为XML的元素名
[XmlArrayAttribute("Hobbies"), XmlArrayItemAttribute("Hobby", typeof(string))]
public System.Collections.ArrayList Hobbies = new System.Collections.ArrayList();
//序列化名为'EmailAddresses'的ArrayList数组,并将'EmailAddress'作为XML的元素名
[XmlArrayAttribute("EmailAddresses"), XmlArrayItemAttribute("EmailAddress", typeof(EmailAddress))]
public System.Collections.ArrayList EmailAddresses = new System.Collections.ArrayList();
#endregion
#region Constructor
public Customer()
{
}
#endregion
#region Properties
[XmlIgnoreAttribute()]//序列化时忽略这个共有属性,因为在序列化时'PictureByteArray'共有属性替代了它
public Bitmap Picture
{
get { return picture; }
set { picture = value; }
}
[XmlElementAttribute("Picture")]//序列化这个共有属性,将其元素名设定为'Picture'
public byte[] PictureByteArray
{
get
{
if (picture != null)
{
// 由于使用System.Xml.Serialization.XmlSerializer类不能自动序列化/反序列化位图
// 因而Bitmap对象作为一个字节数组保存到XML文件中,当XML文件被加载时,转换成位图。
// 使用System.ComponentModel.TypeConverterBitmap实现从一个Bitmap对象转换为字节
// 数组。使用System.IO.MemoryStream实现从一个字节数组转换回Bitmap对象。
TypeConverter BitmapConverter = TypeDescriptor.GetConverter(picture.GetType());
return (byte[])BitmapConverter.ConvertTo(picture, typeof(byte[]));
}
else
{
return null;
}
}
set
{
if (value != null)
{
picture = new Bitmap(new MemoryStream(value));
}
else
{
picture = null;
}
}
}
#endregion
}
/// <summary>
/// 序列化格式类型
/// </summary>
public enum SerializedFormat
{
Binary, //二进制序列化格式
Document //XML序列化格式
}
//将该类定义为'static',则可以直接调用类中的方法函数,而不需实例化该类, <T>表明该类是范型类.
public static class ObjectXMLSerializer<T> where T : class //指定参数T必须是类
{
#region Load methods
/// <summary>
/// 加载一个XML文档(文档为Document格式)对象
/// </summary>
/// <example>
/// <code>
/// serializableObject = ObjectXMLSerializer<SerializableObject>.Load(@"C:\XMLObjects.xml");
/// </code>
/// </example>
/// <param name="path">被加载的文件的路径</param>
/// <returns>返回一个T类类型的对象</returns>
public static T Load(string path)
{
T serializableObject = LoadFromDocumentFormat(null, path, null);
return serializableObject;
}
/// <summary>
/// 加载一个XML文档(文档为使用指定的格式序列化)对象
/// </summary>
/// <example>
/// <code>
/// serializableObject = ObjectXMLSerializer<SerializableObject>.Load(@"C:\XMLObjects.xml", SerializedFormat.Binary);
/// </code>
/// </example>
/// <param name="path">被加载的文件的路径</param>
/// <param name="serializedFormat">XML的序列化格式</param>
/// <returns>返回一个用指定的格式序列化的XML文件的对象</returns>
public static T Load(string path, SerializedFormat serializedFormat)
{
T serializableObject = null;
switch (serializedFormat)
{
case SerializedFormat.Binary:
serializableObject = LoadFromBinaryFormat(path, null);
break;
case SerializedFormat.Document:
default:
serializableObject = LoadFromDocumentFormat(null, path, null);
break;
}
return serializableObject;
}
/// <summary>
/// 加载一个XML文档(文档为Document格式)对象,并且支持额外的数据类型以使反序列化时自定义类型能包含在对象中
/// </summary>
/// <example>
/// <code>
/// serializableObject = ObjectXMLSerializer<SerializableObject>.Load(@"C:\XMLObjects.xml", new Type[] { typeof(MyCustomType) });
/// </code>
/// </example>
/// <param name="path">被加载的文件的路径</param>
/// <param name="extraTypes">额外的数据类型以使反序列化时自定义类型能包含在对象中</param>
/// <returns>返回一个XML文件对象</returns>
public static T Load(string path, System.Type[] extraTypes)
{
T serializableObject = LoadFromDocumentFormat(extraTypes, path, null);
return serializableObject;
}
/// <summary>
/// 加载一个位于指定的隔离储存区中XML文档(文档为Document格式)对象
/// </summary>
/// <example>
/// <code>
/// serializableObject = ObjectXMLSerializer<SerializableObject>.Load("XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly());
/// </code>
/// </example>
/// <param name="fileName">位于用于装载对象的指定的隔离储存区中的文件名</param>
/// <param name="isolatedStorageDirectory">包含XML文件的隔离储存区目录</param>
/// <returns>返回一个位于指定的隔离储存区中的XML文件对象</returns>
public static T Load(string fileName, IsolatedStorageFile isolatedStorageDirectory)
{
T serializableObject = LoadFromDocumentFormat(null, fileName, isolatedStorageDirectory);
return serializableObject;
}
/// <summary>
/// 加载一个位于指定的隔离储存区中的XML文档(文档为使用指定的格式序列化)对象
/// </summary>
/// <example>
/// <code>
/// serializableObject = ObjectXMLSerializer<SerializableObject>.Load("XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), SerializedFormat.Binary);
/// </code>
/// </example>
/// <param name="fileName">位于用于装载对象的隔离储存区中的文件名</param>
/// <param name="isolatedStorageDirectory">包含XML文件的隔离储存区目录</param>
/// <param name="serializedFormat">XML的序列化格式</param>
/// <returns>返回一个位于指定的隔离储存区中的XML文件对象</returns>
public static T Load(string fileName, IsolatedStorageFile isolatedStorageDirectory, SerializedFormat serializedFormat)
{
T serializableObject = null;
switch (serializedFormat)
{
case SerializedFormat.Binary:
serializableObject = LoadFromBinaryFormat(fileName, isolatedStorageDirectory);
break;
case SerializedFormat.Document:
default:
serializableObject = LoadFromDocumentFormat(null, fileName, isolatedStorageDirectory);
break;
}
return serializableObject;
}
/// <summary>
/// 加载一个位于指定的隔离储存区中XML文档(文档为Document格式)对象并且支持额外的数据类型以使反序列化时自定义类型能包含在对象中
/// </summary>
/// <example>
/// <code>
/// serializableObject = ObjectXMLSerializer<SerializableObject>.Load("XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), new Type[] { typeof(MyCustomType) });
/// </code>
/// </example>
/// <param name="fileName">位于用于装载对象的隔离储存区中的文件名</param>
/// <param name="isolatedStorageDirectory">包含XML文件的隔离储存区目录</param>
/// <param name="extraTypes">额外的数据类型以使反序列化时自定义类型能包含在对象中</param>
/// <returns>返回一个位于指定的隔离储存区中的XML文件对象</returns>
public static T Load(string fileName, IsolatedStorageFile isolatedStorageDirectory, System.Type[] extraTypes)
{
T serializableObject = LoadFromDocumentFormat(null, fileName, isolatedStorageDirectory);
return serializableObject;
}
#endregion
#region Private Methods
private static FileStream CreateFileStream(IsolatedStorageFile isolatedStorageFolder, string path)
{
FileStream fileStream = null;
if (isolatedStorageFolder == null)
fileStream = new FileStream(path, FileMode.OpenOrCreate);
else
fileStream = new IsolatedStorageFileStream(path, FileMode.OpenOrCreate, isolatedStorageFolder);
return fileStream;
}
private static T LoadFromBinaryFormat(string path, IsolatedStorageFile isolatedStorageFolder)
{
T serializableObject = null;
using (FileStream fileStream = CreateFileStream(isolatedStorageFolder, path))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
serializableObject = binaryFormatter.Deserialize(fileStream) as T;
}
return serializableObject;
}
private static T LoadFromDocumentFormat(System.Type[] extraTypes, string path, IsolatedStorageFile isolatedStorageFolder)
{
T serializableObject = null;
using (TextReader textReader = CreateTextReader(isolatedStorageFolder, path))
{
XmlSerializer xmlSerializer = CreateXmlSerializer(extraTypes);
serializableObject = xmlSerializer.Deserialize(textReader) as T;
}
return serializableObject;
}
private static TextReader CreateTextReader(IsolatedStorageFile isolatedStorageFolder, string path)
{
TextReader textReader = null;
if (isolatedStorageFolder == null)
textReader = new StreamReader(path);
else
textReader = new StreamReader(new IsolatedStorageFileStream(path, FileMode.Open, isolatedStorageFolder));
return textReader;
}
private static TextWriter CreateTextWriter(IsolatedStorageFile isolatedStorageFolder, string path)
{
TextWriter textWriter = null;
if (isolatedStorageFolder == null)
textWriter = new StreamWriter(path);
else
textWriter = new StreamWriter(new IsolatedStorageFileStream(path, FileMode.OpenOrCreate, isolatedStorageFolder));
return textWriter;
}
private static XmlSerializer CreateXmlSerializer(System.Type[] extraTypes)
{
Type ObjectType = typeof(T);
XmlSerializer xmlSerializer = null;
if (extraTypes != null)
xmlSerializer = new XmlSerializer(ObjectType, extraTypes);
else
xmlSerializer = new XmlSerializer(ObjectType);
return xmlSerializer;
}
private static void SaveToDocumentFormat(T serializableObject, System.Type[] extraTypes, string path, IsolatedStorageFile isolatedStorageFolder)
{
using (TextWriter textWriter = CreateTextWriter(isolatedStorageFolder, path))
{
XmlSerializer xmlSerializer = CreateXmlSerializer(extraTypes);
xmlSerializer.Serialize(textWriter, serializableObject);
}
}
private static void SaveToBinaryFormat(T serializableObject, string path, IsolatedStorageFile isolatedStorageFolder)
{
using (FileStream fileStream = CreateFileStream(isolatedStorageFolder, path))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(fileStream, serializableObject);
}
}
#endregion
#region Save methods
/// <summary>
/// 存储一个对象到XML文档(文档为Document格式)中
/// </summary>
/// <example>
/// <code>
/// SerializableObject serializableObject = new SerializableObject();
///
/// ObjectXMLSerializer<SerializableObject>.Save(serializableObject, @"C:\XMLObjects.xml");
/// </code>
/// </example>
/// <param name="serializableObject">存储到文档中的序列化对象</param>
/// <param name="path">存储序列化对象的文件的路径</param>
public static void Save(T serializableObject, string path)
{
SaveToDocumentFormat(serializableObject, null, path, null);
}
/// <summary>
/// 存储一个对象到XML文档(文档为指定的序列化格式)中
/// </summary>
/// <example>
/// <code>
/// SerializableObject serializableObject = new SerializableObject();
///
/// ObjectXMLSerializer<SerializableObject>.Save(serializableObject, @"C:\XMLObjects.xml", SerializedFormat.Binary);
/// </code>
/// </example>
/// <param name="serializableObject">存储到文档中的序列化对象</param>
/// <param name="path">存储序列化对象的文件的路径</param>
/// <param name="serializedFormat">XML的序列化格式</param>
public static void Save(T serializableObject, string path, SerializedFormat serializedFormat)
{
switch (serializedFormat)
{
case SerializedFormat.Binary:
SaveToBinaryFormat(serializableObject, path, null);
break;
case SerializedFormat.Document:
default:
SaveToDocumentFormat(serializableObject, null, path, null);
break;
}
}
/// <summary>
/// 存储一个对象到XML文档(文档为Document格式)中,并且支持额外的数据类型以使序列化时自定义类型能包含在对象中
/// </summary>
/// <example>
/// <code>
/// SerializableObject serializableObject = new SerializableObject();
///
/// ObjectXMLSerializer<SerializableObject>.Save(serializableObject, @"C:\XMLObjects.xml", new Type[] { typeof(MyCustomType) });
/// </code>
/// </example>
/// <param name="serializableObject">存储到文档中的序列化对象</param>
/// <param name="path">存储序列化对象的文件的路径</param>
/// <param name="extraTypes">额外的数据类型以使序列化时自定义类型能包含在对象中</param>
public static void Save(T serializableObject, string path, System.Type[] extraTypes)
{
SaveToDocumentFormat(serializableObject, extraTypes, path, null);
}
/// <summary>
/// 存储一个对象到位于指定的隔离储存区中的XML文档(文档为Document格式)中
/// </summary>
/// <example>
/// <code>
/// SerializableObject serializableObject = new SerializableObject();
///
/// ObjectXMLSerializer<SerializableObject>.Save(serializableObject, "XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly());
/// </code>
/// </example>
/// <param name="serializableObject">存储到文档中的序列化对象</param>
/// <param name="fileName">位于指定的隔离储存区中的用于存储对象的文件名</param>
/// <param name="isolatedStorageDirectory">包含XML文件的隔离储存区目录</param>
public static void Save(T serializableObject, string fileName, IsolatedStorageFile isolatedStorageDirectory)
{
SaveToDocumentFormat(serializableObject, null, fileName, isolatedStorageDirectory);
}
/// <summary>
/// 存储一个对象到位于指定的隔离储存区中的XML文档(文档为指定的序列化格式)中
/// </summary>
/// <example>
/// <code>
/// SerializableObject serializableObject = new SerializableObject();
///
/// ObjectXMLSerializer<SerializableObject>.Save(serializableObject, "XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), SerializedFormat.Binary);
/// </code>
/// </example>
/// <param name="serializableObject">存储到文档中的序列化对象</param>
/// <param name="fileName">位于指定的隔离储存区中的用于存储对象的文件名</param>
/// <param name="isolatedStorageDirectory">包含XML文件的隔离储存区目录</param>
/// <param name="serializedFormat">XML的序列化格式</param>
public static void Save(T serializableObject, string fileName, IsolatedStorageFile isolatedStorageDirectory, SerializedFormat serializedFormat)
{
switch (serializedFormat)
{
case SerializedFormat.Binary:
SaveToBinaryFormat(serializableObject, fileName, isolatedStorageDirectory);
break;
case SerializedFormat.Document:
default:
SaveToDocumentFormat(serializableObject, null, fileName, isolatedStorageDirectory);
break;
}
}
/// <summary>
/// 存储一个对象到位于指定的隔离储存区中的XML文档(文档为Document格式)中,并且支持额外的数据类型以使序列化时自定义类型能包含在对象中
/// </summary>
/// <example>
/// <code>
/// SerializableObject serializableObject = new SerializableObject();
///
/// ObjectXMLSerializer<SerializableObject>.Save(serializableObject, "XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), new Type[] { typeof(MyCustomType) });
/// </code>
/// </example>
/// <param name="serializableObject">存储到文档中的序列化对象</param>
/// <param name="fileName">位于指定的隔离储存区中的用于存储对象的文件名</param>
/// <param name="isolatedStorageDirectory">包含XML文件的隔离储存区目录</param>
/// <param name="extraTypes">额外的数据类型以使序列化时自定义类型能包含在对象中</param>
public static void Save(T serializableObject, string fileName, IsolatedStorageFile isolatedStorageDirectory, System.Type[] extraTypes)
{
SaveToDocumentFormat(serializableObject, null, fileName, isolatedStorageDirectory);
}
#endregion
}
SOAP(Simple Object Access Protocol),简单对象访问协议,是在分散或分布式的环境中交换信息的简单的协议,是一个基于XML的协议,是Web服务的一个工业标准。虽然SOAP被广泛用于Web服务,但也可以使用它作为一个对象序列化的编码格式。
使用SOAP格式序列化对象时,就必须用Serializable
特性标记类。只有这样,类才能被序列化。SoapFormatter
类驻留在System.Runtime.Serialization.Formatters.Soap
命名空间中。
[Serializable]
public class Customer
{
private int _mID;
private string _mfirstname;
private string _mlastname;
private string _mphone;
private string _mnotes;
public int CustomerID
{
get { return _mID; }
set { _mID = value; }
}
public string FirstName
{
get { return _mfirstname; }
set { _mfirstname = value; }
}
public string LastName
{
get { return _mlastname; }
set { _mlastname = value; }
}
public string HomePhone
{
get { return _mphone; }
set { _mphone = value; }
}
public string Notes
{
get { return _mnotes; }
set { _mnotes = value; }
}
}
序列化
public void Serialization(Customer cus, string fileName)
{
FileStream stream = new FileStream(fileName, FileMode.Create);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, cus);
}
反序列化
public Customer Deserialization(string fileName)
{
Customer cus;
FileStream stream = new FileStream(fileName, FileMode.Open);
SoapFormatter formatter = new SoapFormatter();
cus = (Customer)formatter.Deserialize(stream);
stream.Close();
return cus;
}
实现自定义SOAP序列化的方式有两种:
ISerializable
接口从.NET 2.0开始第一种方式就被第二种方式所取代,因此这里采用第二种方式实现自定义SOAP序列化。
假如相对普通用户保护你的序列化的XML数据。比如你想在序列化数据时,对数据实现Base64编码,使普通读者不能阅读的内容。而在反序列化时,这些数据需要实现Base64编码模式的解码。在这种情况下,自定义序列化属性将派上用场。
[Serializable]
public class Customer
{
#region Variables
private int _mID;
private string _mfirstname;
private string _mlastname;
private string _mphone;
private string _mnotes;
#endregion
#region Properties
public int CustomerID
{
get { return _mID; }
set { _mID = value; }
}
public string FirstName
{
get { return _mfirstname; }
set { _mfirstname = value; }
}
public string LastName
{
get { return _mlastname; }
set { _mlastname = value; }
}
public string HomePhone
{
get { return _mphone; }
set { _mphone = value; }
}
public string Notes
{
get { return _mnotes; }
set { _mnotes = value; }
}
#endregion
#region Methods
private string Encode(string str)
{
// 将数据转化为Base64格式
byte[] data = ASCIIEncoding.ASCII.GetBytes(str);
return Convert.ToBase64String(data);
}
private string Decode(string str)
{
// 将Base64格式字符串转换为普通字符串
byte[] data = Convert.FromBase64String(str);
return ASCIIEncoding.ASCII.GetString(data);
}
[OnSerializingAttribute]
public void OnSerializing(StreamingContext context)
{
_mfirstname = Encode(_mfirstname);
_mlastname = Encode(_mlastname);
_mphone = Encode(_mphone);
_mnotes = Encode(_mnotes);
}
[OnSerializedAttribute]
public void OnSerialized(StreamingContext context)
{
_mfirstname = Decode(_mfirstname);
_mlastname = Decode(_mlastname);
_mphone = Decode(_mphone);
_mnotes = Decode(_mnotes);
}
[OnDeserializingAttribute]
public void OnDeserializing(StreamingContext context)
{
//no code here
}
[OnDeserializedAttribute]
public void OnDeserialized(StreamingContext context)
{
_mfirstname = Decode(_mfirstname);
_mlastname = Decode(_mlastname);
_mphone = Decode(_mphone);
_mnotes = Decode(_mnotes);
}
#endregion
}
四种方法分别用四种特性加以标记。这些特性允许你通过使用前置和后置的方法自定义序列化和反序列化过程。
OnSerializingAttribute
在数据进行序列化前被调用
OnSerializedAttribute
在序列化数据完成后被调用
OnDeserializingAttribute
在数据反序列化前被调用
OnDeserializedAttribute
在数据反序列化后被调用
序列化
public void Serialization(Customer cus, string fileName)
{
FileStream stream = new FileStream(fileName, FileMode.Create);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, cus);
}
反序列化
public Customer Deserialization(string fileName)
{
Customer cus;
FileStream stream = new FileStream(fileName, FileMode.Open);
SoapFormatter formatter = new SoapFormatter();
cus = (Customer)formatter.Deserialize(stream);
stream.Close();
return cus;
}