C#中的Serializable

     Serializable 表示序列化。那么什么是序列化呢?何时何地采用序列化?

一、序列化的一些简单概念(也有称为串行化)
       序列化是指存储和获取磁盘文件、内存或其他地方中的对象。序列化后的对象可以在网络之间进行传输。

       在序列化时,所有的实例数据都保存到存储介质上,在取消序列化时,对象会被还原,且不能与其原实例区别开来。

       只需给类添加Serializable属性,就可以实现序列化实例的成员。:[Serializable]

      与之对比,并行化是序列化的逆过程,数据从存储介质中读取出来,并赋给类的实例变量。

      栗子1:

[Serializable]
public class Person
{public Person()
  {
  }
public int Age;
public int WeightInPounds;
}

  栗子2:如果需要对部分字段序列化部分不序列化,可以按照如下方法实现:

[Serializable]  //序列化 
public class Person 
{public Person() 
  { 
  } 
  public int Age; 
[NonSerialized]//非序列化
public int WeightInPounds;
}

        在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。

以下是网络上的一些理论,可以参考参考慢慢理解一下:

      1、 公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。

      2、对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。

      3、类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。
      4、当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值

二、基本序列化
要使一个类可序列化,最简单的方法是使用 Serializable 属性对它进行标记,如下所示,栗子实现:
[Serializable]
public class MyObject ...{
   
public int num1 = 0;
   
public int num2 = 0;
   
public String str = null;
}

以下代码片段说明了如何将此类的一个实例序列化为一个文件:
MyObject obj 
= new MyObject();
obj.num1 
= 5;
obj.num2 
= 12;
obj.str 
= "一些字符串";
IFormatter formatter 
= new BinaryFormatter();
Stream stream 
= new FileStream("MyFile.bin", FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
本例使用二进制格式化程序进行序列化。只需创建一个要使用的流和格式化程序的实例,然后调用格式化程序的 Serialize 方法。流和要序列化的对象实例作为参数提供给此调用。类中的所有成员变量(甚至标记为 
private 的变量)都将被序列化。
将对象还原到它以前的状态也非常容易。首先,创建格式化程序和流以进行读取,然后让格式化程序对对象进行反序列化。

三、自定义序列化

     可以通过在对象上实现 ISerializable 接口来自定义序列化过程。

     这一功能在反序列化后成员变量的值失效时尤其有用,但是需要为变量提供值以重建对象的完整状态。

     要实现 ISerializable,需要实现 GetObjectData 方法以及一个特殊的构造函数,在反序列化对象时要用到此构造函数。

     以下代码示例说明了如何在前一部分中提到的 MyObject 类上实现 ISerializable。
[Serializable]
public class MyObject : ISerializable
...{
   
public int num1;
   
public int num2;
   
public String str;
   
public MyObject()
   
...{
   }

   
protected MyObject(SerializationInfo info, StreamingContext context)
   
...{
     num1 
= info.GetInt32("i");
     num2 
= info.GetInt32("j");
     str 
= info.GetString("k");
   }

   
public virtual void GetObjectData(SerializationInfo info,
StreamingContext context)
   
...{
     info.AddValue(
"i", num1);
     info.AddValue(
"j", num2);
     info.AddValue(
"k", str);
   }

}

   在序列化过程中调用 GetObjectData 时,需要填充方法调用中提供的 SerializationInfo 对象。

       只需按名称/值对的形式添加将要序列化的变量。其名称可以是任何文本。只要已序列化的数据足以在反序列化过程中还原对象,便可以自由选择添加至 SerializationInfo 的成员变量。如果基对象实现了 ISerializable,则派生类应调用其基对象的 GetObjectData 方法。

       需要强调的是,将 ISerializable 添加至某个类时,需要同时实现 GetObjectData 以及特殊的构造函数。如果缺少 GetObjectData,编译器将发出警告。但是,由于无法强制实现构造函数,所以,缺少构造函数时不会发出警告。如果在没有构造函数的情况下尝试反序列化某个类,将会出现异常。在消除潜在安全性和版本控制问题等方面,当前设计优于 SetObjectData 方法。例如,如果将 SetObjectData 方法定义为某个接口的一部分,则此方法必须是公共方法,这使得用户不得不编写代码来防止多次调用 SetObjectData 方法。可以想象,如果某个对象正在执行某些操作,而某个恶意应用程序却调用此对象的 SetObjectData 方法,将会引起一些潜在的麻烦。

以上内容转载于网络资料,大家可以看看博客,更多详细内容查看一下内容(在前面添加3个w,后面加入“.html ”即可)
cnblogs.com/zwl12549/archive/2007/08/14/854718

四、我们的实战应用

     [Serializable]

 public partial class Plan
 {
  public Plan()
  {}
   private decimal _产品编号;
  private string _产品名称;.html

public decimal 产品编号
  {
   set{ _产品编号=value;}
   get{return _产品编号;}
  }

  public string 产品名称
  {
   set{ _产品名称=value;}
   get{return _产品名称;}
  }

}

**************************************************************************************************************************************************************************************

❤永葆一颗纯洁、宽容平和、仁慈谦卑和意气风发的心!

态度决定一切     努力改变命运

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值