2015-07-20 68 views
1

我正在创建一个vb.net应用程序,它需要能够反序列化在不同应用程序中序列化的文件以及序列化可以在其他应用程序中反序列化的文件。Type.GetType在SerializationBinder中返回Nothing

我想通过使用SerializationBinder在序列化/反序列化期间转换类型使这项工作。使用This article from MSDN作为参考,这是我在这一点....

在我的反序列化功能:

myDeserializer.Binder = New TypeConverter() 
openCount = DirectCast(myDeserializer.Deserialize(stream), Count) 

然后:

Class TypeConverter 

    Inherits SerializationBinder 

    Public Overrides Function BindToType(assemblyName As String, typeName As String) As Type 

     Dim returnType As Type = Nothing 

     If assemblyName = "[name from other application]" Then 
      assemblyName = Assembly.GetExecutingAssembly().FullName 
     End If 

     If typeName = "[other application namespace].Count" Then 
      typeName = "Count" 
     End If 

     returnType = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName)) 

     Return returnType 

    End Function 

End Class 

的如果陈述是真实的,所以assemblyName和typeName正确设置。但是returnType没有被设置 - 它仍然没有。我不知道为什么。

请注意,我在两个应用程序中都有相同的类(即Count,这是它们之间序列化/反序列化的类型)。

谢谢!

+0

不是没有,但你可以通过使用[protobuf网]避免组件之间共享数据的问题(https://www.nuget.org/packages/protobuf-net /)而不是BinaryFormatter。与BF不同,它不会将汇编文化级信息编码到输出中 – Plutonix

+1

是'typeName =“Count”'仅用于演示目的吗?我相信通常它会有一个命名空间限定符。即'typeName =“rootNamespace.Count”' – TnTinMn

+0

@TnTinMn - “Count”是被序列化/反序列化的对象类型。当您在自己的名称空间中引用对象类型时,不必在前面指定名称空间。我改变了“从其他应用程序类型”的文字,这可能有助于更清楚地说明。 – Andarta

回答

0

好的,事实证明,在这种情况下(在此使用中使用Type.GetType),它不起作用,除非在类型之前指定名称空间。所以我有typeName = "Count"我不得不将其改为typeName = "[my project].Count"https://msdn.microsoft.com/en-us/library/a87che9d%28v=vs.110%29.aspx

它也证明,这个函数重复进入的每一个类型(不只是具体什么是反序列化,但对于每种类型的属性)。因此,因为我的“Count”类型包含其他自定义类型的属性,还有一些是其他自定义类型的列表,所以我必须确保每个类型都得到正确转换。

我现在在这里:在逐步完成过程中,看起来一切正常。但是,在它转换了第一个类型为自定义类型结构的列表之后,在尝试转换下一个类型时,我得到一个参数异常。

这是现在的代码:

Public Overrides Function BindToType(assemblyName As String, typeName As String) As Type 

    If assemblyName.Contains("[other project]") Then 
     assemblyName = Assembly.GetExecutingAssembly().FullName 
    End If 

    If typeName.Contains("System.Collections.Generic.List`1[[[Other Project].[Type],") Then 
      typeName = String.Format("System.Collections.Generic.List`1[[[my project].[type]], {0}", Assembly.GetExecutingAssembly().FullName) 
    ElseIf typeName.Contains("System.Collections.Generic.List`1[[[Other Project].[type]+[structure],") Then 
      typeName = String.Format("System.Collections.Generic.List`1[[[My project].[Type]+[Structure], {0}", Assembly.GetExecutingAssembly().FullName) 
    ElseIf typeName.Contains("[Other Project]") Then 
      typeName = Replace(typeName, "[Other Project]", "[My Project]") 
    End If 

    Return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName)) 

End Function 

所以System.Collections.Generic.List`1 [[[我的项目] [类型] + [结构]是一个自定义的列表类型的结构。它涉及到的第一个似乎转换很好,但随后试图转换无论是未来的时候,我得到这个:

附加信息: 类型的“System.Runtime.Serialization.TypeLoadExceptionHolder”对象不能被 转换为 'System.Collections.Generic.List`1 [My Project.Type + Structure]'。

在这种情况下的类型和结构是以前转换的类型...不是在抛出此异常时正在转换的类型。

不知道是怎么回事....

+0

嗯,我是盲目的......事实证明,问题是我在每个结尾处都缺少了一对括号 例如:更改: “typeName = String.Format(”System.Collections.Generic.List'1 [[[my project]。[type]],{0}“,Assembly .GetExecutingAssembly()。FullName)“ 收件人: ”typeName = String.Format(“System.Collections.Generic.List'1 [[[my project]。[type]],{0}]]”,Assembly .GetExecutingAssembly()。FullName)“ 为什么我没有得到一个错误,直到它试图转换特定的结构列表和之前的所有东西似乎工作,我没有想法。 – Andarta

相关问题