【问题标题】:Type.GetType returns Nothing in SerializationBinderType.GetType 在 SerializationBinder 中没有返回任何内容
【发布时间】:2015-10-09 20:44:52
【问题描述】:

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

我正在尝试通过使用 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

If 语句为真,因此 assemblyName 和 typeName 设置正确。但是 returnType 没有设置 - 它仍然是 Nothing。我也不知道为什么。

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

谢谢!

【问题讨论】:

  • 不是没有,但是你可以通过使用Protobuf-Net而不是BinaryFormatter来避免程序集之间共享数据的问题。与 BF 不同,它不会将程序集文化类信息编码到输出中
  • typeName = "Count" 仅用于演示目的吗?我相信通常它会有一个命名空间限定符。即typeName = "rootNamespace.Count"
  • @TnTinMn - “Count”是正在序列化/反序列化的对象类型。当您在自己的命名空间中引用对象类型时,您不必在前面指定命名空间。我更改了“从其他应用程序输入”的文本,这可能有助于更清晰。
  • @Andarta - 来自documentation for Type.GetType,“要获取的类型的程序集限定名称。...如果该类型在当前执行的程序集中或在Mscorlib.dll中,就足够了提供由其命名空间限定的类型名称。"
  • @TnTinMn - 这无助于 returnType 没有被设置为任何东西并且保持 Nothing 的问题。此外,我试图反序列化的类型来自不同的程序集……我是否必须确保返回的类型指定了我正在运行的程序集才能使其正常工作?

标签: vb.net serialization type-conversion deserialization


【解决方案1】:

好的,事实证明,在这种情况下(在此使用中使用 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[[[My project].[Type]+[Structure] 是自定义类型结构的列表。它涉及的第一个似乎转换得很好,但是当尝试转换下一个时,我得到了这个:

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

在这种情况下,Type 和 Structure 是之前转换的类型...而不是抛出此异常时当前正在转换的类型。

不知道这里发生了什么......

【讨论】:

  • 好吧,我是盲人......事实证明问题是我在每个语句的末尾都缺少几个括号来转换一些东西的列表。例如:更改:“typeName = String.Format("System.Collections.Generic.List1[[[my project].[type]], {0}", Assembly.GetExecutingAssembly().FullName)" To: "typeName = String.Format("System.Collections.Generic.List1[[[my project].[type]], {0}]]", Assembly.GetExecutingAssembly().FullName) “为什么直到它尝试专门转换结构列表并且之前的所有内容似乎都有效之后我才收到错误,我没有任何想法。
猜你喜欢
  • 2018-07-30
  • 2016-07-24
  • 1970-01-01
  • 2016-06-23
  • 2018-04-05
  • 1970-01-01
  • 2020-11-22
  • 2021-10-02
  • 2021-01-01
相关资源
最近更新 更多