zoukankan      html  css  js  c++  java
  • 程序中,序列化与反序列化

    在某些需求下,需要将一个类进行序列化,存入数据库,等另一个操作从数据库中取出,再反序列化成类.

    一般实现:

     #region 把一个对象序列化成流
            /// <summary>
            /// 把一个对象序列化成流
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            internal byte[] SerializeObject(object obj)
            {
                MemoryStream m = new MemoryStream();
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(m, obj);
                //再把MemoryStream   流转成byte[]形式!   
                byte[] buffer = m.GetBuffer();
    
                m.Close();
                m.Dispose();
                return buffer;
            }
            #endregion
    
            #region 把一个流转成对象
            /// <summary>
            /// 把一个流转成对象
            /// </summary>
            /// <param name="buffer"></param>
            /// <returns></returns>
            internal object UnSerializeObject(byte[] buffer)
            {
                MemoryStream m = new MemoryStream(buffer);
                BinaryFormatter deserializer = new BinaryFormatter();
                object obj = (deserializer.Deserialize(m));//反序列化得到的对象   
                m.Close();
                m.Dispose();
                return obj;
            }
            #endregion
        }
    

    当需求发生变化,序列化与反序列不在一个project(需要序列化的类写在project中,而非共同的ClassLibrary)中进行时,用以上方法反序列化就会出错,会提示找不到类.

    类的信息:

    [NameSpace.ClassName,assemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]
    

    此时就需要重写SerializationBinder,修改类的命空间

    代码:

     internal static object UnSerializeObject(byte[] buffer)
            {
                MemoryStream m = new MemoryStream(buffer);
                BinaryFormatter deserializer = new BinaryFormatter();
                deserializer.Binder = new OverrideSerializationBinder();
                object obj = deserializer.Deserialize(m);//反序列化得到的对象   
    
                m.Close();
                m.Dispose();
                return obj;
            }
    
            /// <summary>
            /// 重写SerializationBinder ,让序列化的对象从当前数据程序集中取出.
            /// </summary>
            sealed class OverrideSerializationBinder : System.Runtime.Serialization.SerializationBinder
            {
              
                public override Type BindToType(string assemblyName, string typeName)
                {
                    return Type.GetType( typeName);
                }
            }
    

    重写SerializationBinder后,看似不错了.但有时候,也会碰上到麻烦,比如,你需要序列化的类中有泛型的存在,或者assemblyName不相同,NameSpace也不相同.

        [Serializable]
        public class class1
        {
            List<class2> Class2List;
        }
            [Serializable]
        public class class2
        {
           
        }
    
    

    此时在BindToType中截取到的typeName就是为以下信息,又回到了上一错误.

    例:

    System.Collections.Generic.List`1[[NameSpace.ClassName, assemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
    

    解决方法:

     internal static object UnSerializeObject(byte[] buffer, Type type)
            {
                MemoryStream m = new MemoryStream(buffer);
                BinaryFormatter deserializer = new BinaryFormatter();
                deserializer.Binder = new OverrideSerializationBinder() { NewNameSpace = type.FullName.Substring(0, type.FullName.LastIndexOf(".")) };
                object obj = deserializer.Deserialize(m);//反序列化得到的对象   
    
                m.Close();
                m.Dispose();
                return obj;
            }
    
            /// <summary>
            /// 重写SerializationBinder ,让序列化的对象从当前数据程序集中取出.
            /// </summary>
            sealed class OverrideSerializationBinder : System.Runtime.Serialization.SerializationBinder
            {
                public string OldNameSpace = string.Empty;
                public string NewNameSpace;
                public override Type BindToType(string assemblyName, string typeName)
                {
                    //Type t = Type.GetType("System.Collections.Generic.List`1[["+NewNameSpace+".MarketMediaCondition]]");
                    
                    //得到旧的命名空间名称
                    if (OldNameSpace == string.Empty)
                        OldNameSpace = typeName.Substring(0, typeName.LastIndexOf("."));
    
                    //针对处理有泛型的
                    if (typeName.IndexOf("System.Collections.Generic") == 0)
                    {
                        typeName = typeName.Split(',')[0];
                        typeName += "]]";
                    }
    
    
                    string newName = typeName.Replace(OldNameSpace, NewNameSpace);
                    return Type.GetType(newName);
                }
            }
    

    或许还有更好的解决方法.

    希望大家能讨论一下.

  • 相关阅读:
    Android学习小Demo一个显示行线的自定义EditText
    Android中自定义checkbox样式
    android圆角View实现及不同版本这间的兼容
    android下大文件分割上传
    drwtsn32.exe 遇到问题须要关闭。我们对此引起的不便表示抱歉
    【分享】深入浅出WPF全系列教程及源码
    iOS国际化时遇到的错误:read failed: the data couldn&#39;t be read because it isn&#39;t in the correct format.
    void及void指针含义的深刻解析
    堆和栈的差别(转过无数次的文章)
    sizeof,终极无惑(上)
  • 原文地址:https://www.cnblogs.com/SoGood/p/1829476.html
Copyright © 2011-2022 走看看