【发布时间】:2011-06-16 15:29:09
【问题描述】:
在花了几个小时在 Internet 上搜索解决方案并尝试了一些解决方案后,我终于决定自己发布我的问题。
[问题背景]
我正在开发一个应用程序,它将分两部分进行部署:
- 一个 XML Importer 工具:它的作用是加载/读取一个 xml 文件以填充一些数据结构,然后将其序列化为二进制文件。
- 最终用户应用程序:它将加载由 XML 导入器生成的二进制文件,并对恢复的数据结构做一些事情。
目前,我仅将 XML 导入器用于这两个目的(这意味着我首先加载 xml 并将其保存到二进制文件,然后我重新打开 XML 导入器并加载我的二进制文件)。
[实际问题]
这工作得很好,我能够在 XML 加载后恢复我拥有的所有数据,只要我使用我的 XML Importer 的相同版本来做到这一点。这是不可行的,因为我至少需要两种不同的构建,一种用于 XML 导入器,另一种用于最终用户应用程序。请注意,我用于测试的两个版本的 XML Importer 在源代码和数据结构方面完全相同,唯一的区别在于构建号(为了强制不同的构建,我只需在某处添加一个空间并重新构建)。
所以我想做的是:
- 构建我的 XML 导入器版本
- 打开 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 导入器)。
[潜在解决方案]
我确实相信它来自大会周围的某个地方,因为我阅读了许多关于此的帖子和文章。但是,我已经有一个自定义 Binder 来处理程序集名称的差异,如下所示:
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;
}
你们中有人知道我该如何解决它吗?太棒了,请漂亮:)
【问题讨论】:
-
您是否在使用强命名程序集?这可能是它无法识别类相同的原因。
-
说实话,我不知道关于装配的第一件事,今天是我第一次不得不绕过这些。我已经看到有很多关于这些的 msdn 页面,尽管我没有时间阅读它们,因为我在下午晚些时候偶然发现了它们。因此,要回答您的问题,我没有修改任何有关程序集的内容,也没有设置任何特殊内容;我不知道默认情况下程序集是否是强命名的(在这种情况下我使用这些)或不是(在这种情况下我不应该使用强命名的程序集)。
标签: exception types versioning deserialization .net-assembly