反序列化跨程序集移动的类型

本文关键字:类型 移动 程序集 反序列化 | 更新日期: 2023-09-27 17:50:57

我有一堆类型已经从一个程序集移动到另一个程序集。我试图通过使用SerializationBinder将使用旧程序集序列化为新程序集中类型的反序列化数据。

EDIT:程序集的根命名空间与程序集名称相同。旧的程序集已不存在。

sealed class TypeMapBinder : SerializationBinder
    {
        public override Type BindToType( string assemblyName, string typeName )
        {
            Type typeToDeserialize = null;
            if ( assemblyName.Contains( "old namespace" ) )
                typeToDeserialize = Type.GetType( typeName.Replace( "old namespace", "new namespace" ) );
            else
                typeToDeserialize = Type.GetType( String.Concat( typeName, ", ", assemblyName ) );
            return typeToDeserialize;
        }
    }

反序列化代码看起来像这样-

using ( MemoryStream ms = new MemoryStream( byteArr ) )             {
                BinaryFormatter formatter = new BinaryFormatter( );
                formatter.Binder = new TypeMapBinder( );
                return formatter.Deserialize( ms );             
}

当我尝试反序列化时,我得到一个错误,它试图加载旧的程序集。

无法加载文件或程序集"旧程序集"或其依赖关系。系统找不到指定的文件

反序列化跨程序集移动的类型

我想我也遇到了同样的问题。

我的SerializationBinder的BindToType方法不发出任何类型,它引用旧的程序集,但是,BinaryFormatter仍然尝试加载旧的程序集:

System.IO.FileNotFoundException : Could not load file or assembly 'Old.Interfaces, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, ref StackCrawlMark stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, ref StackCrawlMark stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, ref StackCrawlMark stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection)
   at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, ref StackCrawlMark stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.Load(String assemblyString)
   at System.UnitySerializationHolder.GetRealObject(StreamingContext context)
   at System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHolder holder)
   at System.Runtime.Serialization.ObjectManager.DoFixups()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
   [...]

如果我为AppDomain.CurrentDomain.AssemblyResolve添加一个处理程序来加载New.Interfaces而不是Old.Interfaces,它会抛出另一个异常:

System.TypeLoadException : Could not load type 'Old.Interfaces.MyClass' from assembly 'New.Interfaces, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
   at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at System.UnitySerializationHolder.GetRealObject(StreamingContext context)
   at System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHolder holder)
   at System.Runtime.Serialization.ObjectManager.DoFixups()

然而,BindToType方法已经为Old.Interfaces.MyClass类型调用了,正如我所说的,在BindToType中,我不返回可能引用旧类的单个类型。

此外,如果我改变了被反序列化的二进制数据,使得字符串Old的出现被New取代,对象图最终被加载。我对这个解决方案不太满意。

我自己也遇到了这个问题,而且几乎无法修复。

我将一些类型从一个程序集移动到另一个程序集,现在我在旧版本中序列化的文件不能反序列化。我的SerializationBinder成功地解析了每个类型(包括最终导致异常的类型),但我仍然得到错误。直到后来,在反序列化器中的DoFixup例程启动的代码段中,它才崩溃。

结果是我的一个序列化类型有一个类型为类型为的成员(我知道令人困惑)。当反序列化时,存储在此Type属性中的Type信息不会经过SerializationBinder,而是在内部解析并失败。AssemblyResolve也不会修复它。

除了手动解析该文件之外,反序列化该文件的唯一方法是将旧版本与可以读取它的先前程序集打包,然后将其保存为类型中立的东西。

我也遇到了同样的问题:类型被移动到另一个程序集,有一个自定义绑定器,它返回正确的类型,但typeloadeexception生成。

有帮助的东西实际上是:https://stackoverflow.com/a/19490593/434298我的意思是将[assembly:TypeForwardedTo(typeof(TheType))]添加到最初具有该类型的汇编中…

所以对于你的问题,我建议尝试这个,如果将需要使汇编没有真正的源代码,但只是那个[assembly:]

希望这将帮助另一个可怜的灵魂:|