4

我有一堆类型已从一个程序集转移到另一个程序集。我正在尝试使用SerializationBinder将使用旧程序集序列化的数据序列化为新程序集中的类型。

编辑:程序集的根命名空间与程序集名称相同。旧程序集不再存在。

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

当我尝试反序列化时,在尝试加载旧程序集时出现错误。

无法加载文件或程序集“旧程序集”或其依赖项之一。该系统找不到指定的文件。

4

3 回答 3

1

我想我看到了同样的问题。

我的 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,则最终加载对象图。我对这个解决方案不太满意。

于 2013-04-11T12:15:46.197 回答
0

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

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

事实证明,我的一个序列化类型有一个Type 类型的成员(我知道这很令人困惑)。存储在此 Type 属性中的 Type 信息在反序列化时不会通过 SerializationBinder,但会在内部解析并失败。AssemblyResolve 也不会修复它。

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

于 2019-03-27T14:01:33.743 回答
0

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

实际上有帮助的事情是:https ://stackoverflow.com/a/19490593/434298 我的意思是添加[assembly:TypeForwardedTo(typeof(TheType))]到最初具有该类型的程序集...

因此,对于您的问题,我建议您尝试一下,如果需要制作没有真正源代码的程序集,而只是 [程序集:]

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

于 2020-06-17T10:00:48.887 回答