基础命名空间:序列化_自定义序列化 System.Runtime.Serialization
( (From Msdn) 自定义序列化是控制类型的序列化和反序列化的过程,通过控制序列化,可以确保序列化兼容性。换而言之,在不中断类型核心功能的情况下,可在类型的不同版本之间序列化和反序列化。
重要提示:在早于 .NET Framework 4 的版本中,部分受信任的程序集中自定义用户数据的序列化是使用 GetObjectDatamethod() 完成的。 从版本 4.0 开始,该方法将标记有 SecurityCriticalAttribute 特性,该特性阻止在部分受信任的程序集中执行。 若要解决此情况,请实现 ISafeSerializationData 接口)
实现方法:
通过自定义类实现接口ISerializable来实现,需要实现接口的GetObjectData方法,添加一个特殊的构造函数,这个构造函数的参数必须与GetObjectData方法的参数相同(在反序列化时调用),如果缺少GetObjectData,编译器会发出警告,但是,鉴于无法强制现实构造函数,如果不存在构造函数,则不会发出任何警告,但此时如果尝试对某个对象进行反序列化,将会发生异常。
ISerializable接口代码:
using System; using System.Runtime.InteropServices; using System.Security; namespace System.Runtime.Serialization { // 摘要: // 允许对象控制其自己的序列化和反序列化过程。 [ComVisible(true)] public interface ISerializable { // 摘要: // 使用将目标对象序列化所需的数据填充 System.Runtime.Serialization.SerializationInfo。 // // 参数: // info: // 要填充数据的 System.Runtime.Serialization.SerializationInfo。 // // context: // 此序列化的目标(请参见 System.Runtime.Serialization.StreamingContext)。 // // 异常: // System.Security.SecurityException: // 调用方没有所要求的权限。 [SecurityCritical] void GetObjectData(SerializationInfo info, StreamingContext context); } }
其中参数 info 用来存放将要序列化或反序列化的对象的数据
context 描述给定的序列化流的源和目标,并提供一个由调用方定义的附加上下文
自定义Goods类实现ISerializable接口
[Serializable] public class Goods:ISerializable { /// <summary> /// 名称 /// </summary> public string name { get; set; } /// <summary> /// 价格 /// </summary> public double price { get; set; } /// <summary> /// 分类 /// </summary> public string type { get; set; } public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("name", name); info.AddValue("price", price); //info.AddValue("type", type); //此属性不序列化 } public Goods() { } //声明为私有的或受保护的,防止直接使用它 protected Goods(SerializationInfo info, StreamingContext context) { name = info.GetString("name"); price = info.GetDouble("price"); //type = info.GetString("type"); //此属性无法反序列化
} }
分析:在实现 GetObjectData 方法时,最常调用的SerializationInfo的方法是AddValue,这个方法具有针对所有标准类型(int、char等等)的重载版本,将待序列化变量以名称和值对的形式添加;(而 StreamingContext 参数描述给定的序列化流的源和目标,这样就可以知道是将对象序列化到持久性存储还是在将他们跨进程或机器序列化)。而在反序列化时,我们调用SerializationInfo提供的一组GetValue方法,他们针对所有标准类型数据执行各种AddValue重载版本的逆操作。
在要序列化的时候我们通过AddValue()方法往info中填充数据,序列化程序将保存在info中的数据进行序列化。
而当要反序列化的时候,我们从info中用GetValue()将数据取出,赋值给对应的属性
测试代码:
Goods good = new Goods(); good.name = "苹果"; good.price = 10; good.type = "水果"; string dir = System.AppDomain.CurrentDomain.BaseDirectory; //序列化 IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream(dir + "test.bin", FileMode.Create, FileAccess.Write); formatter.Serialize(stream, good); stream.Close();//必须关闭 //反序列化 IFormatter reformatter = new BinaryFormatter(); Stream filestream = new FileStream(dir + "test.bin", FileMode.Open, FileAccess.Read); //返回Object类型,必须强制转换 Goods newgood = (Goods)reformatter.Deserialize(filestream); filestream.Close(); Console.WriteLine("名称:"+newgood.name); Console.WriteLine("价格:"+newgood.price); Console.WriteLine("类型:"+newgood.type); Console.ReadLine();
运行结果:type属性没有序列化
参考 http://msdn.microsoft.com/zh-cn/library/ty01x675.aspx