澳门新葡萄京娱乐场C#序列化和反序列化

这篇文章主要讲述XML与对象的序列化与反序列化。并且会附上一些简单的序列化与反序列化方法,供大家使用。
假设我们在一个Web项目中有这样两个类

序列化和反序列化我们可能经常会听到,其实通俗一点的解释,序列化就是把一个对象保存到一个文件或数据库字段中去,反序列化就是在适当的时候把这个文件再转化成原来的对象使用。
序列化和反序列化最主要的作用有:
1、在进程下次启动时读取上次保存的对象的信息
2、在不同的AppDomain或进程之间传递数据
3、在分布式应用系统中传递数据

public class Member
    {
      public string Num { get; set; }
      public string Name { get; set; }
    }
    public class Team
    {
       public  string Name;
       public  List<Member> Members { get; set; }
    }

引用:

假设我们需要把Team类的一个实例POST到一个URL,
当然,使用Form隐藏域提交就可以完成该功能。
如果该Team包括30条数据呢? 为了区分每个Member,我们得给参数的名字加上后缀。这就要一大串的隐藏域来完成:

1.给要序列化的类加上Serializable特性

<!–使用Razor来演示–>
@model Team
<form id=”submitForm” action=””
method=”post”>
<input type=”hidden” name=”TeamName” value=”@Model.Name” />
<input type=”hidden” name=”MemberNum1″
value=”@Model.Members[0].Num” />
<input type=”hidden” name=”MemberName1″
value=”@Model.Members[0].Name” />

<!–省略28X2个input标签–>
<input type=”hidden” name=”MemberNum30″
value=”@Model.Members[29].Num” />
<input type=”hidden” name=”MemberName30″
value=”@Model.Members[29].Name” />
</form>
<script type=”text/javascript”>
    document.getElementById(“submitForm”).submit();
</script>

澳门新葡萄京娱乐场 1澳门新葡萄京娱乐场 2Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

还敢想象一下如果Team再复杂一些,嵌套再多一些的情况么?
呃,即使你愿意这么传数据,对方看到一坨参数名就够头疼了。
我们都知道对象是不能在网络中直接传输的,不过还有补救的办法。
XML(Extensible Markup
Language)
可扩展标记语言,本身就被设计用来存储数据,任何一个对象都可以用XML来描述。以Team类为例:

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
//序列化靠反射实现
namespace SerializeExsample
{
    //序列化就是将对象转换为容易传输的格式在各个程序之间共享
    //必须给可序列化的对象加上Serializable特性
    [Serializable]
    public class User
    {
        //[NonSerialized]只能在字段上加上该特性表示不会序列化字段
        public string Name { get; set; }
        public int Age { get; set; }
    }
    
    class Program
    {
       static void Main()
        {
           //Serailize
            User user = new User { Name = “Sonven”, Age = 35 };
            BinaryFormatter format = new BinaryFormatter();
            Stream stream = new FileStream(“temp.t”, FileMode.Create);
            format.Serialize(stream, user);//参数为一个Stream,object
            stream.Dispose();
           //Deserialize
            stream = new FileStream(“temp.t”, FileMode.Open, FileAccess.Read);
            User newuser =format.Deserialize(stream) as User; //Deserialize
            if (newuser != null) Console.WriteLine(“Deserialize user:Name{0},Age{1}”, newuser.Name, newuser.Age);
            stream.Dispose();  
            File.Delete(“temp.t”);//Delete Temp Data
            Console.ReadKey();

<?xml version=”1.0″ encoding=”utf-8″?>
<Team xmlns:xsi=””
xmlns:xsd=”;
  <Name>Development</Name>
  <Members>
    <Member>
      <Num>001</Num>
      <Name>Marry</Name>
    </Member>
    <Member>
      <Num>002</Num>
      <Name>John</Name>
    </Member>
  </Members>
</Team>

        }
    }
}

这样一个XML文档就表示了Team一个实例。
聪明的看官应该已经想到,XML是可以作为对象信息的载体在网络中传输,因为它是文本形式的。
怎么进行XML文档与对象的相互转换呢?

2.实现序列化接口

XmlSerializer类就是干这个活的。       命名空间:System.Xml.Serialization
     程序集:System.Xml(在 system.xml.dll 中)
现在这里展示了一个提供序列化与反序列化方法的EncodeHelper类。
Deserialize方法将XML字符串转换为指定类型的对象;
Serialize方法则将对象转换为XML字符串。

 

/// <summary>
    /// 提供xml文档序列化 反序列化
    /// </summary>
    public sealed class EncodeHelper
    {
        /// <summary>
        /// 反序列化XML字符串为指定类型
        /// </summary>
        public static object Deserialize(string Xml, Type ThisType)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(ThisType);
            object result;
            try
            {
                using (StringReader stringReader = new
StringReader(Xml))
                {
                    result = xmlSerializer.Deserialize(stringReader);
                }
            }
            catch (Exception innerException)
            {
                bool flag = false;
                if (Xml != null)
                {
                    if
(Xml.StartsWith(Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble())))
                    {
                        flag = true;
                    }
                }
                throw new ApplicationException(string.Format(“Couldn’t
parse XML: ‘{0}’; Contains BOM: {1}; Type: {2}.”,
                Xml, flag, ThisType.FullName), innerException);
            }
            return result;
        }
        /// <summary>
        /// 序列化object对象为XML字符串
        /// </summary>
        public static string Serialize(object ObjectToSerialize)
        {
            string result = null ;
            try
            {
            XmlSerializer xmlSerializer = new
XmlSerializer(ObjectToSerialize.GetType());

澳门新葡萄京娱乐场 3澳门新葡萄京娱乐场 4Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                XmlTextWriter xmlTextWriter = new
XmlTextWriter(memoryStream, new UTF8Encoding(false));
                xmlTextWriter.Formatting = Formatting.Indented;
                xmlSerializer.Serialize(xmlTextWriter,
ObjectToSerialize);
                xmlTextWriter.Flush();
                xmlTextWriter.Close();
                UTF8Encoding uTF8Encoding = new UTF8Encoding(false,
true);
                result=
uTF8Encoding.GetString(memoryStream.ToArray());
            }
            }
            catch (Exception innerException)
            {
                throw new ApplicationException(“Couldn’t Serialize
Object:” + ObjectToSerialize.GetType().Name, innerException);
            }
            return result;
        }
    }

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

要使用这个类需要添加以下引用
using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
下面我们用一个控制台程序来演示一下这个类是如何工作的。这里是程序的Main函数。

namespace SerializeExsample.Custorm
{
    [Serializable]
    public class User:ISerializable
    {
        public string Name { get; set; }
        public int Age { get; set; }

static void Main(string[] args)
        {
            List<Member> Members = new List<Member>();
            Member member1 = new Member { Name = “Marry”, Num = “001”
};
            Member member2 = new Member { Name = “John”, Num = “002”
};
            Members.Add(member1);
            Members.Add(member2);
            Team team = new Team { Name = “Development”, Members =
Members };
            var xml =EncodeHelper.Serialize(team);//序列化
            Console.Write(xml);//打印序列化后的XML字符串
            Console.ReadLine();
            Team newTeam = EncodeHelper.Deserialize(xml, typeof(Team))
as Team;//反序列化时需要显式的进行类型转换
            Console.WriteLine(“Team
Name:”+newTeam.Name);//显示反序列化后的newTeam对象
            foreach (var member in newTeam.Members)
            {
                Console.WriteLine(“Member Num:” + member.Num);
                Console.WriteLine(“Member Name:” + member.Name);
            }
            Console.ReadLine();
        }

        public User() { }
        //反序列化
        //此构造函数用于创建反序列化后的对象
        public User(SerializationInfo info, StreamingContext context)
        {
            //SerializationInfo的Value键值区分大小些,如果Age改为age将抛出错误
            Age =(int) info.GetValue(“Age”, typeof(int));
           // Name = info.GetValue(“Name”, typeof(string)) as string;
        }

在执行完Console.Write(xml)这行代码后,就可以看到打印出来的XML文档了。

        //序列化,在里面添加要被序列化的属性
        //实现ISerializable的GetObjectData方法
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(“Age”, this.Age);
            //info.AddValue(“Name”, this.Name);
        }
    }
    
    class Program
    {
        static void Main()
        {
            User user=new User{Name=”Jack”,Age=22};
            //Serialize
            BinaryFormatter format = new BinaryFormatter();
            Stream stream = new FileStream(“temp.t”, FileMode.Create);
            format.Serialize(stream, user);
            stream.Dispose();
            //Deserialize
            stream = new FileStream(“temp.t”, FileMode.Open, FileAccess.Read);
            user = format.Deserialize(stream) as User;
            stream.Dispose();
            if (user != null) Console.WriteLine(“Deserialized user Name:{0},Age:{1}”, user.Name, user.Age);
            
            Console.ReadKey();
            //反序列后的对象Name为null,Age为22
        }
    }
}

<?xml version=”1.0″ encoding=”utf-8″?>
<Team xmlns:xsi=””
xmlns:xsd=”;
  <Name>Development</Name>
  <Members>
    <Member>
      <Num>001</Num>
      <Name>Marry</Name>
    </Member>
    <Member>
      <Num>002</Num>
      <Name>John</Name>
    </Member>
  </Members>
</Team>

3.使用XMLSerializer

与我在文章开头给出的例子是一模一样的。
最终反序列化出来的newTeam对象打印出来是这样的结果。
Team Name:Development
Member Num:001
Member Name:Marry
Member Num:002
Member Name:John
回到我们开头的Web通信的例子,
利用XML序列化与反序列化来进行对象传递,我们只需要把需要传递的对象序列化为XML字符串,使用一个隐藏域进行form提交就可以搞定咯!
接收方再将接收到的XML字符串反序列化成预设的对象即可。前提是双方必须约定序列化与反序列化的过程一致,且对象相同。

 

最后我们来看一下怎么利用一些特性来控制序列化与反序列化操作的过程。我们把开始的类改一下:

澳门新葡萄京娱乐场 5澳门新葡萄京娱乐场 6Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Member
    {
        [XmlElement(“Member_Num”)]
        public string Num { get; set; }
        public string Name { get; set; }
    }
    [XmlRoot(“Our_Team”)]
    public class Team
    {
        [XmlIgnore]public string Name;
        public List<Member> Members { get; set; }
    }

using System.IO;
using System.Xml;
using System.Xml.Serialization;

然后我们再次执行刚才的控制台程序,序列化结果变成了这样:

namespace SerializeExsample.Xml
{
   public class User
    {
       public string Name { get; set; }
       public int Age{get;set;}
       [XmlIgnore]  //忽略对属性序列化
       public DateTime RegDate { get; set; }
    }

<?xml version=”1.0″ encoding=”utf-8″?>
<Our_Team xmlns:xsi=””
xmlns:xsd=”;
  <Members>
    <Member>
      <Member_Num>001</Member_Num>
      <Name>Marry</Name>
    </Member>
    <Member>
      <Member_Num>002</Member_Num>
      <Name>John</Name>
    </Member>
  </Members>
</Our_Team>

   class Program
   {
       static void Main() 
       {
           User user=new User{Name=”Sonven”,Age=35,RegDate=DateTime.Now};
           //Serialize
           XmlSerializer serializer = new XmlSerializer(typeof(User));//Param:Type要被序列化的对象类型
           Stream stream=new FileStream(“temp.xml”,FileMode.Create);
           serializer.Serialize(stream, user);
           stream.Dispose();
           /***********************************************
            * 因为RegDate应用了XmlIgnore特性,xml文件不包含
            * 序列化将生成XML文件类容如下,
              <?xml version=”1.0″?>
              <User>
              <Name>Sonven</Name>
              <Age>35</Age>
              </User>
            * ******************************************/
           //Deserialize
           stream = new FileStream(“temp.xml”,FileMode.Open,FileAccess.Read);
           user = serializer.Deserialize(stream) as User;
           stream.Dispose();
           if (user != null) Console.WriteLine(“Deserialize User Name:{0},Age:{1}”, user.Name, user.Age);
           Console.ReadKey();
       }
   }
}

本来的根节点Team变成了Our_Team,Member的子节点Num变成了Member_Num,并且Team的Name子节点被忽略了。
可见特性XmlRoot可以控制根节点的显示和操作过程,XmlElement则针对子节点。如果某些成员被标记XmlIgnore,则在序列化与反序列化过程中会被忽略。
这些特性的具体内容可以在MSDN查看,就不多讲了。
有了这些知识,在网络中传递对象数据应该已经难不倒各位看官了把。^_^

源代码下载SerializeExsample.rar

发表评论

电子邮件地址不会被公开。 必填项已用*标注