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

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

    希望大家能讨论一下.

  • 相关阅读:
    EntityFramework 启用迁移 EnableMigrations 报异常 "No context type was found in the assembly"
    JAVA 访问FTP服务器示例(2)
    NuGet Package Manager 更新错误解决办法
    JAVA 访问FTP服务器示例(1)
    RemoteAttribute 的使用问题
    诡异的 javascript 变量
    javascript apply用法
    Babun 中文乱码
    GSM呼叫过程
    转站博客园
  • 原文地址:https://www.cnblogs.com/SoGood/p/1829476.html
Copyright © 2011-2022 走看看