反序列化问题:从不同的程序版本反序列化时出错 [英] Deserialization problem: Error when deserializing from a different program version

查看:474
本文介绍了反序列化问题:从不同的程序版本反序列化时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



[问题背景]

我终于决定自己发布我的问题,经过几个小时的时间花费在互联网上搜索解决方案。 / strong>



我正在开发一个应用程序,分为两部分:




  • 一个XML导入器工具:它的作用是加载/读取一个xml文件,以填充一些数据结构,这些数据结构随后被序列化成二进制文件。

  • 最终用户应用程序:它将加载由XML导入器生成的二进制文件,并使用恢复的数据结构进行一些操作。



现在,我只使用XML导入器用于两个目的(意思是我首先加载xml并将其保存到二进制文件,然后重新打开XML导入器并加载我的二进制文件)。



[实际问题]



这个工作很好,我能够恢复XML加载后的所有数据,只要我使用与XML Importer相同的构建体,就可以 。这是不可行的,因为我至少需要两个不同的构建,一个用于XML导入器,一个用于最终用户应用程序。请注意,我用于我测试的两个版本的XML导入器与源代码和数据结构完全相同,唯一的区别在于编号(强制使用不同的构建I只需在某处添加一个空格并再次创建)。



所以我想要做的是:




  • 构建我的XML导入器版本

  • 打开XML导入器,加载XML文件并将生成的数据结构保存到二进制文件

  • 重建XML导入器

  • 打开新建的XML Importer,加载先前创建的二进制文件并恢复我的数据结构。



此时,我得到一个例外:

  SerializationException:找不到类型' 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代码)
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&值,System.Runtime.Serialization.SerializationInfo& info)

有关您的信息(不知道是否有用或不有),它正在努力反序列化的实际类型是列表,网格是一个自定义类(这是正确的serializab le,因为我可以使用相同版本的XML Importer)。



[潜在解决方案]



我相信它来自大会周围的某个地方,因为我读了很多关于这个的帖子和文章。但是,我已经有一个自定义的Binder处理大会名称的差异,看起来像这样:

  public sealed class VersionDeserializationBinder: SerializationBinder 
{
public override Type BindToType(string assemblyName,string typeName)
{
if(!string.IsNullOrEmpty(assemblyName)&!string.IsNullOrEmpty(typeName) )
{
类型typeToDeserialize = null;
assemblyName = Assembly.GetExecutingAssembly()。FullName;
//以下代码行返回类型。
typeToDeserialize = Type.GetType(String.Format({0},{1},typeName,assemblyName));

return typeToDeserialize;
}

返回null;
}
}

我在反序列化之前分配给BinaryFormatter: / p>

  public static SaveData Load(string filePath)
{
SaveData data = null; // new SaveData );
流流;

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


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

Debug.Log(从+ filePath加载的二进制版本);

返回数据;
}

你们中的任何一个有一个想法,我可以如何解决它?将会很棒,很好,请:)

解决方案

将工作位移动到单独的程序集,并在服务器和客户。根据您对该问题的解释,这应该解决错误版本问题,如果这是核心问题。我也将采取任何模式(即像Grid这样的状态位)到域模型项目,并在两个地方使用它。


I finally decided myself to post my problem, after a couple of hours spent searching the Internet for solutions and trying some.

[Problem Context]

I am developing an application which will be deployed in two parts:

  • an XML Importer tool: its role is to Load/Read an xml file in order to fill some datastructures, which are afterwards serialized into a binary file.
  • the end user application: it will Load the binary file generated by the XML Importer and do some stuff with the recovered data structures.

For now, I only use the XML Importer for both purposes (meaning I first load the xml and save it to a binary file, then I reopen the XML Importer and load my binary file).

[Actual Problem]

This works just fine and I am able to recover all the data I had after XML loading, as long as I do that with the same build of my XML Importer. This is not viable, as I will need at the very least two different builds, one for the XML Importer and one for the end user application. Please note that the two versions of the XML Importer I use for my testing are exactly the same concerning the source code and thus the datastructures, the only difference lies in the build number (to force a different build I just add a space somewhere and build again).

So what I'm trying to do is:

  • Build a version of my XML Importer
  • Open the XML Importer, load an XML file and save the resulting datastructures to a binary file
  • Rebuild the XML Importer
  • Open the XML Importer newly built, load the previously created binary file and recover my datastructures.

At this time, I get an Exception:

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)

For your information (don't know if useful or not), the actual type it is struggling to deserialize is a List, Grid being a custom Class (which is correctly serializable, as I am able to do it when using the same version of XML Importer).

[Potential Solution]

I do believe it comes from somewhere around the Assembly, as I read many posts and articles about this. However, I already have a custom Binder taking care of the differences of Assembly names, looking like this:

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

which I assign to the BinaryFormatter before deserializing here:

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

Do any of you guys have an idea on how I could fix it? Would be awesome, pretty please :)

解决方案

Move the working bits to a separate assembly and use the assembly in both "server" and "client". Based on your explanation of the problem, this should get around the "wrong version" problem, if that is the core issue. I would also take any "models" (i.e. bits of state like Grid) to a domain model project, and use that in both places.

这篇关于反序列化问题:从不同的程序版本反序列化时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆