C# 学习跟踪之序列化

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();
        }
   
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值