反序列化问题:从其他程序版本反序列化时出错

| 在花了几个小时在Internet上寻找解决方案并尝试了一些方法之后,我终于决定发表自己的问题。 [问题背景] 我正在开发一个应用程序,它将分为两个部分: XML导入器工具:其作用是加载/读取xml文件以填充某些数据结构,这些数据结构随后被序列化为二进制文件。 最终用户应用程序:它将加载XML Importer生成的二进制文件,并对恢复的数据结构进行一些处理。 现在,我仅将XML Importer用于这两个目的(这意味着我首先加载xml并将其保存到二进制文件,然后重新打开XML Importer并加载我的二进制文件)。 [实际问题] 这工作得很好,并且只要我使用相同的XML Importer构建即可恢复XML加载后的所有数据。这是不可行的,因为我至少需要两个不同的版本,一个用于XML Importer,一个用于最终用户应用程序。请注意,我在测试中使用的XML Importer的两个版本在源代码和数据结构方面是完全相同的,唯一的区别在于内部版本号(要强制执行不同的内部版本,我只是在某处添加一个空格并进行内部版本再次)。 所以我想做的是: 构建我的XML Importer的版本 打开XML导入器,加载XML文件并将结果数据结构保存到二进制文件 重建XML导入器 打开新建的XML Importer,加载先前创建的二进制文件并恢复我的数据结构。 这时,我得到一个异常:
SerializationException: Could not find type \'System.Collections.Generic.List`1[[Grid, 74b7fa2fcc11e47f8bc966e9110610a6, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]\'.
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadType (System.IO.BinaryReader reader, TypeTag code)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadTypeMetadata (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectInstance (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info)
为了您的信息(不知道是否有用),正在努力反序列化的实际类型是一个列表,网格是一个自定义类(可以正确序列化,因为我可以在使用相同版本时做到这一点) XML Importer)。 [潜在解决方案] 我确实相信它来自大会周围的某个地方,因为我阅读了许多与此有关的帖子和​​文章。但是,我已经有一个自定义的活页夹,负责处理程序集名称的不同,如下所示:
public sealed class VersionDeserializationBinder : SerializationBinder
{ 
    public override Type BindToType( string assemblyName, string typeName )
    { 
        if ( !string.IsNullOrEmpty( assemblyName ) && !string.IsNullOrEmpty( typeName ) )
        { 
            Type typeToDeserialize = null; 
            assemblyName = Assembly.GetExecutingAssembly().FullName; 
            // The following line of code returns the type. 
            typeToDeserialize = Type.GetType( String.Format( \"{0}, {1}\", typeName, assemblyName ) ); 

            return typeToDeserialize; 
        } 

        return null; 
    }
}
我在这里反序列化之前将其分配给BinaryFormatter:
    public static SaveData Load (string filePath) 
    {
        SaveData data = null;//new SaveData ();
        Stream stream;

        stream = File.Open(filePath, FileMode.Open);


        BinaryFormatter bformatter = new BinaryFormatter();
        bformatter.Binder = new VersionDeserializationBinder(); 
        data = (SaveData)bformatter.Deserialize(stream);
        stream.Close();

        Debug.Log(\"Binary version loaded from \" + filePath);

        return data; 
    }
你们中有人对我该如何解决有想法吗?会很棒,漂亮请:)     
已邀请:
        将工作位移动到单独的程序集中,并在“服务器”和“客户端”中使用该程序集。根据您对问题的解释,如果这是核心问题,则应该解决“错误版本”问题。我还将任何“模型”(即像Grid之类的状态位)带到域模型项目中,并在两个地方都使用它。     
        当我遇到相同的问题时,我碰到了您的线程。特别是您的带有Seri​​alizationBinder的代码示例对我有很大帮助。我只需要对其稍作修改即可告诉我自己的程序集与Microsoft程序集之间的区别。希望它对您也有帮助:
sealed class VersionDeserializationBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        Type typeToDeserialize = null;
        string currentAssemblyInfo = Assembly.GetExecutingAssembly().FullName;

        //my modification
        string currentAssemblyName = currentAssemblyInfo.Split(\',\')[0];
        if (assemblyName.StartsWith(currentAssemblyName))assemblyName = currentAssemblyInfo;

        typeToDeserialize = Type.GetType(string.Format(\"{0}, {1}\", typeName, assemblyName));
        return typeToDeserialize;
    }
}
    
        我相信问题是您要告诉它在正在执行的程序集中查找List <>,而实际上是在系统程序集中。如果原始程序集是您的活页夹之一,则仅应在活页夹中重新分配程序集名称。 另外,您可能必须通过解析类型名称并确保当返回参数化的泛型类型时,确保参数类型不是特定于外部程序集,从而专门在活页夹中处理泛型的参数类型。     

要回复问题请先登录注册