C# 二进制序列化(BinaryFormatter),Xml序列化(XmlSerializer),自己模拟写一个Xml序列化过程。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml.Serialization; namespace 序列化 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Person p = new Person(); p.Name ="张三"; p.Age =18; p.Gender = true; using (System.IO.FileStream file = new FileStream("person.dat", FileMode.Create, FileAccess.Write)) { //System.Runtime.Serialization.Formatters.Binary; BinaryFormatter b = new BinaryFormatter(); b.Serialize(file, p); //序列化 } MessageBox.Show("ok"); } private void button2_Click(object sender, EventArgs e) { using (System.IO.FileStream file = new FileStream("person.dat", FileMode.Open, FileAccess.Read)) { BinaryFormatter b = new BinaryFormatter(); Person p = (Person)b.Deserialize(file); //反序列化 MessageBox.Show(p.Name); } } private void button3_Click(object sender, EventArgs e) { List<Person> list = new List<Person>(); Person p = new Person(); p.Name = "张三"; p.Age = 18; p.Gender = true; Person p2 = new Person(); p2.Name = "李四"; p2.Age = 19; p2.Gender = true; list.Add(p); list.Add(p2); //将Person类对象序列化写入流中 using (System.IO.FileStream file = File.OpenWrite("person.xml")) { //System.Xml.Serialization; XmlSerializer xmlSer = new XmlSerializer(typeof(Person)); xmlSer.Serialize(file, p); } //也可以将List集合对象序列化写入到流中,对象是Object类型。 using (System.IO.FileStream file = File.OpenWrite("personList.xml")) { XmlSerializer xmlSer = new XmlSerializer(typeof(List<Person>)); //通过反射指定类型 xmlSer.Serialize(file, list); } MessageBox.Show("ok"); } private void button4_Click(object sender, EventArgs e) { //Xml反序列化 using (System.IO.FileStream file = File.OpenRead("person.xml")) { XmlSerializer xmlSer = new XmlSerializer(typeof(Person)); Person p = (Person)xmlSer.Deserialize(file); MessageBox.Show(p.Name); } } } //程序集“序列化, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中的类型“序列化.Person”未标记为可序列化。 [Serializable] //Serializable 可以被序列化,此类不能被继承。 //XML序列化中不需要此方法! public class Person { private string name; private int age; private bool gender; [XmlIgnore] //XmlIgnoreAttribute 不序列化公共字段或公共读写属性值。 public bool Gender { get { return gender; } set { gender = value; } } public int Age { get { return age; } set { age = value; } } public string Name { get { return name; } set { name = value; } } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml.Serialization; namespace 序列化 { public partial class Form2 : Form { public Form2() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { MyPerson mp = new MyPerson(); mp.Name = "张三"; mp.Age = 18; mp.Gender = true; using (System.IO.FileStream file = new System.IO.FileStream("myPerson.xml", System.IO.FileMode.Create, System.IO.FileAccess.Write)) { //创建自己写的序列化类对象 MyXmlSerializer myXmlSer = new MyXmlSerializer(); //调用序列化方法,保存到文件中。 myXmlSer.Serialize(file, mp); } MessageBox.Show("ok"); } } public class MyPerson { private string name; private int age; private bool gender; [MyXmlIgnore] //添加特性,这个公有的属性将不被序列化,在序列化方法里实现。 public bool Gender { get { return gender; } set { gender = value; } } public int Age { get { return age; } set { age = value; } } public string Name { get { return name; } set { name = value; } } } //模拟写一个序列化方法类 public class MyXmlSerializer { /// <summary> /// 使用指定的 System.IO.Stream 序列化指定的 System.Object 并将 XML 文档写入文件。 /// </summary> /// <param name="stream">用于编写 XML 文档的 System.IO.Stream。</param> /// <param name="o">将要序列化的 System.Object。</param> public void Serialize(System.IO.Stream stream, object o) { //通过反射获取对象类型 Type typeObj = o.GetType(); //创建XML文档 System.Xml.Linq.XDocument xdoc = new System.Xml.Linq.XDocument(); //创建XML元素,获取对象类型类名称作为,XML根节点名称 System.Xml.Linq.XElement xRoot = new System.Xml.Linq.XElement(typeObj.Name); //添加到XML根节点 xdoc.Add(xRoot); //通过反射获取这个类型的所有公共属性 System.Reflection.PropertyInfo[] pinfos = typeObj.GetProperties(); //遍历pinfos每个属性都有创建XML元素 foreach (System.Reflection.PropertyInfo info in pinfos) { //通过每个属性获取它的特性,判断有没有MyXmlIgnoreAttribute特性,如果没有才给序列化。 object[] objAttrs = info.GetCustomAttributes(typeof(MyXmlIgnoreAttribute), false); //当小于等于0时,可判定该属性没有MyXmlIgnoreAttribute特性,可以被序列化。 if (objAttrs.Length <= 0) { System.Xml.Linq.XElement xelet = new System.Xml.Linq.XElement(info.Name, info.GetValue(o)); xRoot.Add(xelet); //添加到根节点下面 } //有MyXmlIgnoreAttribute特性的就不写入XML。 } //保存XML到流中去 xdoc.Save(stream); } } //不序列化属性字段特性 public class MyXmlIgnoreAttribute : Attribute { } }
关于反序列化:
<?xml version="1.0"?>
<PersonRoot>
<Person>
<Age>18</Age>
<Name>张三</Name>
</Person>
<Person>
<Age>19</Age>
<Name>李四</Name>
</Person>
</PersonRoot>
public class PersonRoot { List<Person> perList = new List<Person>(); [XmlElement(ElementName = "Person")] public List<Person> PerList { get { return perList; } set { perList = value; } } }
using (System.IO.FileStream file = File.OpenRead("personList.xml")) { XmlSerializer xmlSer = new XmlSerializer(typeof(PersonRoot)); PersonRoot list = (PersonRoot)xmlSer.Deserialize(file); MessageBox.Show(list.PerList[0].Name); }
XML数据格式,
<ArrayOfPerson>
<Person>
可以直接List<Person>类型反序列化到List<Person>对象中。
Attribute:
Attribute 类将预定义的系统信息或用户定义的自定义信息与目标元素相关联。 目标元素可以是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性、返回值、结构或其他特性。
特性所提供的信息也称为元数据。 元数据可由应用程序在运行时进行检查以控制程序处理数据的方式,也可以由外部工具在运行前检查以控制应用程序处理或维护自身的方式。 例如,.NET Framework 预定义特性类型并使用特性类型控制运行时行为,某些编程语言使用特性类型表示 .NET Framework 常规类型系统不直接支持的语言功能。
所有特性类型都直接或间接地从 Attribute 类派生。 特性可应用于任何目标元素;多个特性可应用于同一目标元素;并且特性可由从目标元素派生的元素继承。 使用 AttributeTargets 类可以指定特性所应用到的目标元素。
Attribute 类提供检索和测试自定义特性的简便方法。 有关使用特性的更多信息,请参见 应用特性和 利用特性扩展元数据。
下面的代码示例演示 Attribute 的用法。
using System; using System.Reflection; // An enumeration of animals. Start at 1 (0 = uninitialized). public enum Animal { // Pets. Dog = 1, Cat, Bird, } // A custom attribute to allow a target to have a pet. public class AnimalTypeAttribute : Attribute { // The constructor is called when the attribute is set. public AnimalTypeAttribute(Animal pet) { thePet = pet; } // Keep a variable internally ... protected Animal thePet; // .. and show a copy to the outside world. public Animal Pet { get { return thePet; } set { thePet = value; } } } // A test class where each method has its own pet. class AnimalTypeTestClass { [AnimalType(Animal.Dog)] public void DogMethod() {} [AnimalType(Animal.Cat)] public void CatMethod() {} [AnimalType(Animal.Bird)] public void BirdMethod() {} } class DemoClass { static void Main(string[] args) { AnimalTypeTestClass testClass = new AnimalTypeTestClass(); Type type = testClass.GetType(); // Iterate through all the methods of the class. foreach(MethodInfo mInfo in type.GetMethods()) { // Iterate through all the Attributes for each method. foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo)) { // Check for the AnimalType attribute. if (attr.GetType() == typeof(AnimalTypeAttribute)) Console.WriteLine( "Method {0} has a pet {1} attribute.", mInfo.Name, ((AnimalTypeAttribute)attr).Pet); } } } } /* * Output: * Method DogMethod has a pet Dog attribute. * Method CatMethod has a pet Cat attribute. * Method BirdMethod has a pet Bird attribute. */