在某些需求下,需要将一个类进行序列化,存入数据库,等另一个操作从数据库中取出,再反序列化成类.
一般实现:
#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); } }
或许还有更好的解决方法.
希望大家能讨论一下.