概述
XML序列化和反序列化是C#的常用技术,实现的方式有很多种,序列化即将对象转化为便于传输的数据格式, 常见的方法有:二进制,字节数组,json字符串,xml字符串等。今天主要通过DataContractSerializer类的WriteObject和ReadObject方法实现.上次讲过XmlSerializer序列化和反序列化,请参考:
代码实现
前台XMAL: 逻辑很简单,主要通过绑定DisplayInfo显示相关信息
<UserControl x:Class="Caliburn.Micro.Hello.DataContractSerializerView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="clr-namespace:Caliburn.Micro.Hello"mc:Ignorable="d"d:DesignHeight="450" d:DesignWidth="800"><Grid><TextBlock Background="White" Height="450" MinWidth="210"VerticalAlignment="Top" TextWrapping="NoWrap" Name="DisplayInfo"/></Grid></UserControl>
后台cs代码:
using System;using System.IO;using System.Reflection;using System.Runtime.Serialization;using System.Text;namespace Caliburn.Micro.Hello{public class DataContractSerializerViewModel : Screen, IViewModel{private StringBuilder stringBuilder = new StringBuilder();public string DisplayInfo { get; set; }public DataContractSerializerViewModel(){DisplayName = "DataContractSerializer";InitData();stringBuilder.AppendLine("success");DisplayInfo = stringBuilder.ToString();}public void InitData(){string fileName = "Programmers.dat";Stream fs = null;fs = FileReset(fs, fileName);//序列化DataContractSerializer dataContractSerializer = new DataContractSerializer(typeof(Person));dataContractSerializer.WriteObject(fs, new Person("zzz", "yyy", 555,new lesson() { English = "eee", Chinese = "ccc" }));//反序列化fs.Position = 0;var p = (Person)dataContractSerializer.ReadObject(fs);//Console.WriteLine($"{p.FirstName},{p.LastName},{p.ID},{p.lesson}");stringBuilder.AppendLine($"{p.FirstName},{p.LastName},{p.ID},{p.lesson}");//自定义属性Person newPerson = new Person();Type type = typeof(Person);InformationAttribute informationAttribute;//Querying Class Attributesforeach (Attribute attr in type.GetCustomAttributes(true)){informationAttribute = attr as InformationAttribute;if (null != informationAttribute){//Console.WriteLine("Description of AnyClass:\n{0} {1}",// informationAttribute.Description, informationAttribute.DefaultValue);stringBuilder.AppendLine($"Description of AnyClass:\n{informationAttribute.Description} " +$"{informationAttribute.DefaultValue}");}}//Querying Class-Method Attributesforeach (MethodInfo method in type.GetMethods()){foreach (Attribute attr in method.GetCustomAttributes(true)){informationAttribute = attr as InformationAttribute;if (null != informationAttribute){//Console.WriteLine("Description of {0}:\n{1} ", method.Name, informationAttribute.Description);stringBuilder.AppendLine($"Description of {method.Name}:\n{informationAttribute.Description} ");}}}//Querying Class-Field (only public) Attributesforeach (FieldInfo field in type.GetFields()){foreach (Attribute attr in field.GetCustomAttributes(true)){informationAttribute = attr as InformationAttribute;if (null != informationAttribute){//Console.WriteLine("Description of {0}:\n{1} {2}", field.Name,// informationAttribute.Description, informationAttribute.DefaultValue);stringBuilder.AppendLine($"Description of { field.Name}:\n{informationAttribute.Description} {informationAttribute.DefaultValue}");//给实例对应字段赋值if (field.FieldType == typeof(string)){newPerson.GetType().GetField(field.Name).SetValue(newPerson, informationAttribute.DefaultValue);}else if (field.FieldType == typeof(Int32)){newPerson.GetType().GetField(field.Name).SetValue(newPerson, Convert.ToInt32(informationAttribute.DefaultValue));}}}}}public FileStream FileReset(Stream fStream, string filename){if (fStream != null){fStream.Close();}File.Delete(filename);return new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);}}[DataContract(Name = "Person", Namespace = "http://www.person.com")]public class Person{[DataMember()][Information(Description = "名称", DefaultValue = "本山")]public string FirstName;[DataMember][Information(Description = "性别", DefaultValue = "赵")]public string LastName;[DataMember()][Information(Description = "序号", DefaultValue = "1")]public int ID;[DataMember()]public lesson lesson;public Person(string newfName, string newLName, int newID, lesson lesson){FirstName = newfName;LastName = newLName;ID = newID;this.lesson = lesson;}public Person(){}}[DataContract()]public class lesson{[DataMember()]public string English { get; set; }[DataMember()]public string Chinese { get; set; }public override string ToString(){return $"[English] = [{English}], " +$"[Chinese] = [{Chinese}], ";}}[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]public class InformationAttribute : Attribute{public string Name { get; set; }public string Description { get; set; }public string Unit { get; set; }public string Range { get; set; }public string AvailableValue { get; set; }public string DefaultValue { get; set; }public double Epsilon { get; set; }public byte Precision { get; set; }public string Parameter { get; set; }public uint FixedSize { get; set; }public NodeType NodeType { get; set; }}//// 摘要:// 节点类型(仅用于Dictionary)public enum NodeType{//// 摘要:// The key of dictKey = 0,//// 摘要:// The Value of dictValue = 1}}
要用DataContractSerializer,首先要引用库:
System.Runtime.Serialization.dll
需要序列化的类前需要用[DataContract]标注,需要序列化的字段需要用
[DataMember]标注,这里还定义了一个自定义属性InformationAttribute,它需要继承自Attribute,使用方法如下:

这里通过反射Type type = typeof(Person);获取类型,通过GetCustomAttributes获取所有自定义特性,通过GetFields()获取当前 当前 System.Type 定义的字段,
给实例对应字段赋值
if (field.FieldType == typeof(string)){newPerson.GetType().GetField(field.Name).SetValue(newPerson, informationAttribute.DefaultValue);}else if (field.FieldType == typeof(Int32)){newPerson.GetType().GetField(field.Name).SetValue(newPerson, Convert.ToInt32(informationAttribute.DefaultValue));}