C#中泛型集合ListT反序列化问题及解决⽅法
⼀、⼀般类型的反序列化程序集问题及处理⽅法
在⼀些应⽤系统中常常有两个⼦系统软件A与B:A软件序列化⼀个数据⽂件,该⽂件将在B软件中使⽤。例如,在15年的交通运输部⼩样本调查数据的审核软件中,A软件就是笔者⾃⼰⽤的审核规则编制软件;B软件则是给⽤户使⽤的审核⼩样本调查数据的客户端软件,该软件只需要使⽤A软件发布的规则即可。笔者的处理⽅法是,A软件序列化审核规则DataTable到⼀个⽂件中,B软件反序列化该⽂件后直接使⽤。
⼀般情况下,A软件序列化类型对象时,将写⼊类型的名称,且该名称包含了程序集的名字(注意,这个是关键),并且B软件通常不与A软件的程序集名相同。因此,在反序列化时将抛出:“处理的异常:  System.Runtime.Serialization.SerializationException: ⽆法到程序集“ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”。这⾥的异常信息中的ConsoleApplication1就是A软件的程序集名。这类异常的解决⽅法是:在反序列化时,更改类型查的程序集名。具体代码如下:
using (FileStream fs = new FileStream("student.dat", FileMode.Open, FileAccess.Read))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Binder = new LocalizedTypeGetter();  // 保证在当前程序集中获取反序列化的类型
Students newObj = (Students)bf.Deserialize(fs);  // 这⾥假设 Students 是⼀个普通类型
Console.WriteLine(newObj.Name);
}
public class LocalizedTypeGetter : System.Runtime.Serialization.SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
assemblyName = System.Reflection.Assembly.GetExecutingAssembly().FullName;  // 当前程序集
return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));    // 从当前程序集中获取类型名,注意,类型的名称空间要相同
}
}
在反序列化时,给序列化类的Binder⽅法⼀个⾃定义的类型LocalizerTypeGetter,该类型重写了BindToType()⽅法,保证在当前程序集中获取类型。
这⾥需要强调的是,反序列化和序列化程序集应该是相同的名称空间(不同的名称空间是否可⾏?笔者尚未做相关测试,因为笔者的AB软件的名称空间是相同的)。
⼆、泛型集合List<T>的反序列化问题及处理⽅法
前⾯介绍的⽅法不能解决泛型集合List<T>的反序列化问题。因为List<T>被.NET框架认为是标准类型,将在mscorlib动态库中查类型,⽽不是在⽤户程序集中查类型,笔者通过调试跟踪BindToType()⽅法发现了这个现象。在尚未到通⽤⽅式前,笔者采取了如
下“笨”的直接⽅法解决:
public class LocalizedTypeGetterEx : LocalizedTypeGetter
{
public override Type BindToType(string assemblyName, string typeName)
{
if (typeName.Contains("List") == true && typeName.Contains(typeof(Student).Name) == true)  // 如果是泛型集合
{
return typeof(List<Student>);  // 直接返回反序列化的类型
}
return base.BindToType(assemblyName, typeName);
}
}
writeline方法属于类派⽣LocalizedTypeGetter类型,再次重写BindToType()⽅法。在再重写⽅法中,判断是否是反序列化需要的泛型集合,如果是则直接返回泛型结合的类型List<T>(如代码中的List<Student>)。此时,只
需要在反序列化时修改代码为 bf.Binder = new LocalizedTypeGetterEx()即可。
上述代码在Win7、Visual Studio 2012、.NET Framework3.5环境下调试通过。
补充:在设计15年⼩样本调查数据处理软件时,使⽤了DataTable保存审核规则,反序列化和序列化只需要考虑上⾯⼀般类型的反序列化⽅法即可。然⽽,最近在做公路养护报表审核软件时,使⽤泛型List<T>保存审核规则记录,在序列化和反序列化时就碰到了反序列化失败的异常。暂时到的⽅法是笨⽅法,希望以后改进为通⽤⽅法。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。