using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Security.Permissions;
namespace TestForMemberwiseClone
{
/*这个类是最原始的类*/
[Serializable]
class MyTestClass
{
public int n1=0;
public int n2=0;
public string name = null;
}
/*这个类是选择序列化用到的类*/
[Serializable]
class MyTestClass_Select
{
public int n1 = 0;
[NonSerialized]public int n2 = 0;
public string name = null;
}
/*这个类是自定义序列化用到的类*/
[Serializable]
public class MyTestClass_SelfDefined : ISerializable
{
public int n1 = 0;
public int n2 = 0;
public String str = null;
public MyTestClass_SelfDefined()
{
}
/*这个构造函数的被保护的,防止被粗心的程序员用了*/
protected MyTestClass_SelfDefined(SerializationInfo info, StreamingContext context)
{
n1 = info.GetInt32("i");
n2 = info.GetInt32("j");
str = info.GetString("k");
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("i", n1);
info.AddValue("j", n2);
info.AddValue("k", str);
}
}
class MyBaseClass
{
public string name;
public string id;
public string score;
}
class MyDevicedClass : MyBaseClass
{
static void Main(string[] args)
{
MyDevicedClass d1 = new MyDevicedClass();
d1.name = "oy";
d1.id = "1103710201";
d1.score = "60";
MyDevicedClass d2 = (MyDevicedClass)d1.MemberwiseClone();
/*
* 刚刚试了下,不加强制转化编译不让通过
* 也就是说MemberwiseClone()创建新的类型实例的type是Object
* 而不是MyDecivedClass
*/
Console.WriteLine("{0} {1} {2}",d2.name,d2.id,d2.score);
Object d3 = d1.MemberwiseClone();
Console.WriteLine("d3's type is {0}", d3.GetType());
Console.WriteLine("d1's type is {0}", d1.GetType());
/*
* 但是现实是残酷的
* 我加了下getType后,发现不是这样的!!!
* MemberwiseClone()创建新的类型实例的type是MyDecivedClass!!
*/
/*
* 没错,d1,d3显示出来都是TestForMemberwiseClone.MyDevicedClass。而不是Object!
* 怎么一回事?怎么解释d2要加强转?为什么同类型的d1和d2要加强转?
* 如果不强转编译器显示:
* 错误 1 无法将类型“object”隐式转换为“TestForMemberwiseClone.MyDevicedClass”。
* 存在一个显式转换(是否缺少强制转换?)
* 为了查找资料我找到了一篇关于memberwiseClone的相关文章
* http://www.cnblogs.com/zhangji/archive/2011/02/23/1961897.html
* 里面有个序列化的关键字:
* [Serializable]在C#中的作用-NET 中的对象序列化
* http://www.cnblogs.com/wddavid/archive/2007/05/08/739456.html
* 哎呀,慢慢看这个序列化,然后在研究下这memberwiseClone吧
*/
/*序列化*/
MyTestClass obj = new MyTestClass();
obj.n1 = 1;
obj.n2 = 24;
obj.name = "oy";
SerializeClass("file.bin", obj);
/*反序列*/
MyTestClass obj2 = new MyTestClass();
IFormatter fmt = new BinaryFormatter();
Stream fromStream = new FileStream("file.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
obj2=(MyTestClass)fmt.Deserialize(fromStream);
Console.WriteLine("obj2's n1 is {0}", obj2.n1);
Console.WriteLine("obj2's n2 is {0}", obj2.n2);
Console.WriteLine("obj2's name is {0}", obj2.name);
fromStream.Close();
/*
* 不采用2进制格式化了,采用SoapFormatter,以便有可移植性!just because xml!
*/
SoapFormatter sfmt = new SoapFormatter();
Stream inputStream = new FileStream("file2.bin", FileMode.Create, FileAccess.Write, FileShare.None);
sfmt.Serialize(inputStream, obj);
inputStream.Close();
/* <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:MyTestClass id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/TestForMemberwiseClone/TestForMemberwiseClone%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<n1>1</n1>
<n2>24</n2>
<name id="ref-3">oy</name>
</a1:MyTestClass>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
不愧是有可移植性!!以上就是那些数据了!
*/
/*选择性序列化*/
MyTestClass_Select obj_s=new MyTestClass_Select();
obj_s.n1 = 11;
obj_s.n2 = 22;
obj_s.name = "oy";
SerializeClass("file_s.bin", obj_s);
/* 选择性反序列化*/
MyTestClass_Select obj_s2 = new MyTestClass_Select();
IFormatter fmt_s2 = new BinaryFormatter();
Stream stream_s2 = new FileStream("file_s.bin", FileMode.Open, FileAccess.Read, FileShare.None);
obj_s2 = (MyTestClass_Select)fmt_s2.Deserialize(stream_s2);
stream_s2.Close();
Console.WriteLine("obj_s2's n1 is:" + obj_s2.n1);
Console.WriteLine("obj_s2's n2 is:" + obj_s2.n2);
Console.WriteLine("obj_s2's name is:" + obj_s2.name);
/*
* 我在这里失意了!我找不到可以把DeSerialize集合成一个函数的方法,你看到的
* DeSerializeClass()函数虽然是这么写,但是没用,因为这个函数少了个东西,
* 这个东西也就是前面我在质疑的一个东西,没错,你猜对了,我少了个强制转化,
* obj=fmt.Deserialize(outputStream);是不行的,应该是 :
* obj=(Class)fmt.Deserialize(outputStream);可是这个Class是不定的,
* 我怎么才能确定下来呢?我想到了GetType()但是不行,因为它返回的是一个字符串。。
* 哎,不纠结了。
* 这是没有选择序列化的结果:
* MTestForMemberwiseClone, Version=1.0.0.0, Culture=neutral,
* PublicKeyToken=null )TestForMemberwiseClone.MyTestClass_Select n1n2name oy
* 这是有选择序列化的结果:
* MTestForMemberwiseClone, Version=1.0.0.0, Culture=neutral,
* PublicKeyToken=null )TestForMemberwiseClone.MyTestClass_Select n1name oy
*/
/*自定义序列化 */
MyTestClass_SelfDefined obj_sd = new MyTestClass_SelfDefined();
obj_sd.n1 = 1;
obj_sd.n2 = 2;
obj_sd.str = "3";
SerializeClass("file_sd.bin",obj_sd);
/* 自定义反序列化*/
MyTestClass_SelfDefined obj_sd2 = new MyTestClass_SelfDefined();
IFormatter fmt_sd2 = new BinaryFormatter();
Stream stream_sd2 = new FileStream("file_sd.bin", FileMode.Open, FileAccess.Read, FileShare.None);
obj_sd2 = (MyTestClass_SelfDefined)fmt_s2.Deserialize(stream_sd2);
stream_sd2.Close();
Console.WriteLine("obj_sd2's n1 is :"+obj_sd2.n1);
Console.WriteLine("obj_sd2's n2 is :" + obj_sd2.n2);
Console.WriteLine("obj_sd2's str is :" + obj_sd2.str);
/*
* 测试了很久,都觉得和想象中不一样,哪里不一样?
* 我先入为主觉得这个特殊的构造函数应该是在序列化时起作用,
* 但是我错了,它是在反序列化的时候才起作用!
* 这样也就解释了为什么我打印出来n1,n2,str都为0(null)
* 因为我一开始没有给这三个变量赋值!哎,为什么我一开始不赋值?
* 因为我在期待这个特殊的构造函数能给我惊喜。。。
* 不吐槽了,说正经的,至今还是没体会到自定义序列化带来的什么不一样啊!!!
*/
/*
* MSDN上说:(针对序列化这个机制)
* 请注意,序列化可使其他代码得以查看或修改本来不可访问的对象实例数据。
* 因此,执行序列化的代码要求指定了 SerializationFormatter 标志的 SecurityPermission。
* 在默认策略下,通过 Internet 下载的代码或 Intranet 代码不会被授予该权限;
* 只有本地计算机上的代码才会被授予该权限。
* 必须对 GetObjectData 方法进行显式保护,方法是要求指定了
* SerializationFormatter 标志的 SecurityPermission 或要求其他专门保护私有数据的权限。
* 也就是说我有必要深入了解下代码安全类啦:
* http://msdn.microsoft.com/zh-cn/library/system.security.permissions.securitypermission(v=vs.80).aspx
*/
}
public static void SerializeClass(string filename, Object obj)
{
IFormatter fmt = new BinaryFormatter();
Stream inputStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None);
fmt.Serialize(inputStream, obj);
inputStream.Close();
}
public static void DeSerializeClass(string fileName, Object obj)
{
IFormatter fmt = new BinaryFormatter();
Stream outputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
obj = fmt.Deserialize(outputStream);
outputStream.Close();
}
}
}
C# 学习跟踪之序列化
最新推荐文章于 2024-09-20 11:17:40 发布