序列化简言之是这样一种能力:能够把复杂的对象(Object)变成某种格式的字符串(常见的格式有xml,string,二进制文件等),这样可以方便的在各种系统中传输或交换(比喻socket编程中的数据包只能用byte[]传输),接收方得到该字符串后,通过反序列化可以还原为复杂对象,进而调用对象的方法或属性 -- 跟反射有点沾边:)
这里先给出一个WinForm的序列化例子,功能为通过打开文件对话框选择一个文件后,构造一个复杂对象,然后序列化为二进制格式,得到该格式后,再反序列化(还原)为复杂对象
Winform中的序列化
- using System;
- using System.IO;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Text;
- using System.Windows.Forms;
- namespace SerializeStudy
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- private void btnSerialize_Click(object sender, EventArgs e)
- {
- OpenFileDialog opendlg = new OpenFileDialog();
- if (opendlg.ShowDialog() == DialogResult.OK)
- {
- #region 得到一个包含"文件内容"的Msg对象
- Msg msg = new Msg();
- msg.ReceiverName = "jimmy";
- msg.SenderName = "yjmyzy";
- msg.Type = MessageType.file;
- FileStream fs = opendlg.OpenFile() as FileStream;
- msg.Body = new byte[fs.Length];
- fs.Read(msg.Body, 0, msg.Body.Length);
- fs.Close();
- #endregion
- #region 将Msg对象序列到内存流中
- MemoryStream ms = new MemoryStream();
- BinaryFormatter binaryFormatter = new BinaryFormatter();
- binaryFormatter.Serialize(ms, msg);
- #endregion
- #region 再将内存流转化为byte[]
- byte[] arrMsg = ms.ToArray();
- ms.Close();
- #endregion
- MessageBox.Show("序列化成功!");
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < arrMsg.Length; i++)
- {
- sb.Append(arrMsg[i].ToString() + ",");
- }
- textBox1.Text = sb.ToString().Trim(',');
- }
- }
- private void btnDeSerialize_Click(object sender, EventArgs e)
- {
- if (textBox1.Text.Trim().Length == 0) { return; }
- #region 先将textbox1中的内容变成byte[]
- string[] arrMsg = textBox1.Text.Trim().Split(',');
- byte[] arrBin = new byte[arrMsg.Length];
- for (int i = 0; i < arrMsg.Length; i++)
- {
- arrBin[i] = byte.Parse(arrMsg[i]);
- }
- #endregion
- try
- {
- IFormatter formatter = new BinaryFormatter();
- MemoryStream ms = new MemoryStream(arrBin);
- Msg msg = formatter.Deserialize(ms) as Msg;
- if (msg != null)
- {
- MessageBox.Show("反序列化成功!" + msg.ReceiverName + "," + msg.SenderName + "," + msg.Type);
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message.ToString());
- }
- }
- }
- /// <summary>
- /// 消息格式
- /// </summary>
- [Serializable]
- public enum MessageType
- {
- txt,
- img,
- file,
- unknown
- }
- /// <summary>
- /// 消息对象
- /// </summary>
- [Serializable]
- public class Msg
- {
- private MessageType _type = MessageType.unknown;
- public MessageType Type
- {
- set { _type = value; }
- get { return _type; }
- }
- public string SenderName { set; get; }
- public string ReceiverName { set; get; }
- public byte[] Body { set; get; }
- }
- }
不过在Silverlight中,传统的序列化方式有很多被精减掉了(比如BinaryFormatter之类),唯一得以保存的只剩下System.Xml.Serialization,所以SL中只能通过xml来序列化对象(虽然xml序列化后的字节数相对Binary有点大,不过我们也别无选择),另外有一点很让人不习惯的是,需要序列化的自定义类中,居然不需要加[Serializable],[DataMember]这类标记!(这一点让我郁闷了好久,还为此在网上疯狂的百度,google为啥sl中不识别Serializable)
1.先定义一个需要序列化的类
自定义类
- namespace SerializeDemo
- {
- /// <summary>
- /// 聊天室消息对象
- /// </summary>
- public class ChatMessage
- {
- public string SenderName { set; get; }
- public string ReceiverName { set; get; }
- public MessageType Type { set; get; }
- public byte[] Body { set; get; }
- public enum MessageType {
- txt,img,file,unknown
- }
- }
- }
2.序列化/反序列化代码示例:
Xaml部分:
- <UserControl x:Class="SerializeDemo.MainPage"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
- <Grid x:Name="LayoutRoot">
- <Grid.RowDefinitions>
- <RowDefinition Height="30"/>
- <RowDefinition Height="*"/>
- </Grid.RowDefinitions>
- <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
- <Button x:Name="btnSerialize" Content="序列化" Width="80" Height="24" Click="btnSerialize_Click"/>
- <Button x:Name="btnDeSerialize" Content="反序列化" Width="80" Margin="10,0,0,0" Height="24" Click="btnDeSerialize_Click"/>
- </StackPanel>
- <TextBox Grid.Row="1" Text="TextBox" TextWrapping="Wrap" d:LayoutOverrides="Height" x:Name="txtResult"/>
- </Grid>
- </UserControl>
Xaml.cs部分:
- using System;
- using System.IO;
- using System.Text;
- using System.Windows;
- using System.Windows.Controls;
- using System.Xml.Serialization;
- namespace SerializeDemo
- {
- public partial class MainPage : UserControl
- {
- public MainPage()
- {
- InitializeComponent();
- }
- private void btnSerialize_Click(object sender, RoutedEventArgs e)
- {
- #region 得到一个复杂对象
- ChatMessage msg = new ChatMessage();
- msg.ReceiverName = "jimmy";
- msg.SenderName = "yjmyzy";
- msg.Type = ChatMessage.MessageType.file;
- msg.Body = new byte[] { 0, 1, 0, 1 };
- #endregion
- MemoryStream ms = new MemoryStream();
- XmlSerializer xml = new XmlSerializer(typeof(ChatMessage));
- try
- {
- xml.Serialize(ms, msg);//将对象序列化为流
- byte[] arr = ms.ToArray();
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < arr.Length; i++)
- {
- sb.Append(arr[i].ToString() + ",");
- }
- txtResult.Text = sb.ToString().Trim(',');
- }
- catch (Exception ex)
- {
- txtResult.Text = ex.Message.ToString();
- }
- }
- private void btnDeSerialize_Click(object sender, RoutedEventArgs e)
- {
- if (txtResult.Text.Trim().Length == 0) { return; }
- #region 先将txtResult中的内容变成byte[]
- string[] arrMsg = txtResult.Text.Trim().Split(',');
- byte[] arrBin = new byte[arrMsg.Length];
- for (int i = 0; i < arrMsg.Length; i++)
- {
- arrBin[i] = byte.Parse(arrMsg[i]);
- }
- #endregion
- MemoryStream ms = new MemoryStream(arrBin);
- XmlSerializer xml = new XmlSerializer(typeof(ChatMessage));
- try
- {
- ChatMessage msg = xml.Deserialize(ms) as ChatMessage;//反序列化为ChatMessage对象
- if (msg != null)
- {
- txtResult.Text = "反序列化成功!" + msg.ReceiverName + "," + msg.SenderName + "," + msg.Type.ToString();
- }
- }
- catch (Exception ex)
- {
- txtResult.Text = ex.Message.ToString();
- }
- }
- }
- }