程序中,序列化与反序列化

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

一般实现:

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

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

希望大家能讨论一下.

原文地址:https://www.cnblogs.com/SoGood/p/1829476.html