none
请教一个很让人郁闷的对象序列化问题 RRS feed

  • 问题

  • 测试代码如下

    对TypeC序列化后再反序列化,结果发现里面collection全为null,这是为什么呢?
    有什么办法可以解决吗?

        [Serializable]
    
        struct TypeA
    
        {
    
            public double A1;
    
            public double A2;
    
            public double A3;
    
            public TypeA(double a)
    
            {
    
                A1 = a;
    
                A2 = a;
    
                A3 = a;
    
            }
    
        }
    
        [Serializable]
    
        class TypeB : ISerializable
    
        {
    
            private readonly List<TypeA> collection = new List<TypeA>();
    
            public TypeB()
    
            {
    
                collection.Add(new TypeA(1));
    
                collection.Add(new TypeA(2));
    
                collection.Add(new TypeA(3));
    
                collection.Add(new TypeA(4));
    
                collection.Add(new TypeA(5));
    
            }
    
            #region ISerializable Members
    
            protected TypeB(SerializationInfo info, StreamingContext context)
    
            {
    
                collection.AddRange(info.GetValue("B", typeof(List<TypeA>)) as List<TypeA>);
    
            }
    
            public void GetObjectData(SerializationInfo info, StreamingContext context)
    
            {
    
                info.AddValue("B", collection, typeof(List<TypeA>));
    
            }
    
            #endregion
    
        }
    
        [Serializable]
    
        class TypeC : ISerializable
    
        {
    
            private readonly List<TypeB> collection = new List<TypeB>();
    
            public TypeC()
    
            {
    
                collection.Add(new TypeB());
    
                collection.Add(new TypeB());
    
                collection.Add(new TypeB());
    
            }
    
            protected TypeC(SerializationInfo info, StreamingContext context)
    
            {
    
                collection.AddRange(info.GetValue("C", typeof(TypeB[])) as TypeB[]);
    
            }
    
            public void GetObjectData(SerializationInfo info, StreamingContext context)
    
            {
    
                info.AddValue("C", collection.ToArray());
    
            }
    
        }
    
        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                using(MemoryStream stream = new MemoryStream())
    
                {
    
                    TypeC c = new TypeC();
    
                    BinaryFormatter formatter = new BinaryFormatter();
    
                    formatter.Serialize(stream, c);
    
                    stream.Seek(0, SeekOrigin.Begin);
    // 反序列化后,结果与预期不一致 TypeC c2 = formatter.Deserialize(stream) as TypeC; } using(MemoryStream stream = new MemoryStream()) { TypeB b = new TypeB(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, b); stream.Seek(0, SeekOrigin.Begin); TypeB b2 = formatter.Deserialize(stream) as TypeB; } using(MemoryStream stream = new MemoryStream()) { TypeB[] b = new TypeB[2]; b[0] = new TypeB(); b[1] = new TypeB(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, b); stream.Seek(0, SeekOrigin.Begin); TypeB[] b2 = formatter.Deserialize(stream) as TypeB[]; } } }
    2009年12月16日 13:44

答案

  • 你好!
         我认为这行代码有问题:
    collection.AddRange(info.GetValue("C" , typeof (TypeB[])) as TypeB[]);
         对象将被彻底重新构造,并且在反序列化期间调用方法可能会产生不良的副作用,因为被调用的方法可能引用在进行此调用时尚未被反序列化的对象引用。
    周雪峰
    2009年12月16日 16:00
    版主

全部回复

  • 你好!
         我认为这行代码有问题:
    collection.AddRange(info.GetValue("C" , typeof (TypeB[])) as TypeB[]);
         对象将被彻底重新构造,并且在反序列化期间调用方法可能会产生不良的副作用,因为被调用的方法可能引用在进行此调用时尚未被反序列化的对象引用。
    周雪峰
    2009年12月16日 16:00
    版主
  • 你好!
         我认为这行代码有问题:
    collection.AddRange(info.GetValue("C" , typeof (TypeB[])) as TypeB[]);
         对象将被彻底重新构造,并且在反序列化期间调用方法可能会产生不良的副作用,因为被调用的方法可能引用在进行此调用时尚未被反序列化的对象引用。
    周雪峰

    对象为readonly,不会再次重建
    这行代码即使改成TypeB[] bs = info.GetValue("C" , typeof (TypeB[])) as TypeB[]; 也会出同样的问题,bs[0] bs[1]... 为null
    2009年12月16日 16:34
  • 这个帖子怎么会移到  XML 与 Web Services 讨论区  这个地方了呢???
    2009年12月17日 1:21
  • 把 ISerializable 接口的方法全部去掉,就可以了。


    This posting is provided "AS IS" with no warranties, and confers no rights. Microsoft Online Community Support
    2009年12月23日 9:33
    版主
  • 把 ISerializable 接口的方法全部去掉,就可以了。


    This posting is provided "AS IS" with no warranties, and confers no rights. Microsoft Online Community Support

    这个方法只能解决这个测试代码的东西,但实际产品中,必须要自己实现ISerializable 接口,比如说加密特殊字段
    2009年12月24日 1:20