System.Type.GetType 方法

本文提供了此 API 参考文档的补充说明。

利用GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean, Boolean)方法重载及其关联的重载(GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>)GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean))将GetType方法的默认实现替换为更加灵活的实现。 通过提供自己的方法来解析类型名称和包含它们的程序集的名称,可以执行以下操作:

  • 控制从中加载类型的程序集的版本。
  • 提供另一个位置来查找不包含程序集名称的类型名称。
  • 使用部分程序集名称加载程序集。
  • 返回公共语言运行时(CLR)未创建的子类 System.Type

例如,在版本容错序列化中,此方法允许使用部分名称搜索“最适合”程序集。 GetType 方法的其他重载需要程序集限定的类型名称,其中包括版本号。

类型系统的备用实现可能需要返回 CLR 未创建的子类 System.Type ;该方法的其他重载 GetType 返回的所有类型都是运行时类型。

使用注意事项

此重载方法及其相关的重载方法将 typeName 解析为类型名称和程序集名称,然后进行解析。 程序集名称的解析发生在类型名称解析之前,因为必须在程序集的上下文中解析类型名称。

注释

如果不熟悉程序集限定类型名称的概念,请参阅 AssemblyQualifiedName 属性。

如果 typeName 不是程序集限定的名称,则跳过程序集解析。 可以在 mscorlib.dll/System.Private.CoreLib.dll 或当前正在执行的程序集的上下文中解析非限定类型名称,或者可以选择在 typeResolver 参数中提供程序集。 在 混合名称解析 部分中,包括或省略不同类型名称解析的程序集名称的效果显示为表。

常规用法说明:

  • 不要将未知或不受信任的调用方的方法传递给 assemblyResolvertypeResolver。 仅使用你提供或熟悉的方法。

    谨慎

    使用未知或不受信任的调用方的方法可能会导致恶意代码特权提升。

  • 如果省略 assemblyResolver 和/或 typeResolver 参数,则参数的值 throwOnError 将传递给执行默认解析的方法。

  • 如果throwOnErrortrue,当TypeLoadException返回typeResolver时,此方法将引发null;当FileNotFoundException返回assemblyResolver时,将引发null

  • 此方法不捕获由 assemblyResolvertypeResolver引发的异常。 你负责解析器方法引发的任何异常。

解析程序集

该方法 assemblyResolver 接收一个 AssemblyName 对象,该对象是通过分析包含在 typeName其中的字符串程序集名称生成的。 如果 typeName 不包含程序集名称, assemblyResolver 则不调用并 null 传递给 typeResolver

如果assemblyResolver未被提供,则使用标准程序集探测机制来查找程序集。 如果 assemblyResolver 已提供,GetType 方法则不会执行标准探测,此时必须确保 assemblyResolver 可处理传递给它的所有程序集。

如果无法解析程序集,该方法 assemblyResolver 应返回 null 。 如果assemblyResolver返回null,则不会调用typeResolver,且不会发生进一步的处理;此外,如果throwOnErrortrue,则会引发FileNotFoundException

AssemblyName如果传递给assemblyResolver的是部分名称,则其一个或多个部分为 null。 例如,如果它没有版本,则 Version 属性为 null. 如果Version属性、CultureInfo属性和GetPublicKeyToken方法全部返回null,那么仅提供了程序集的简单名称。 该方法 assemblyResolver 可以使用或忽略程序集名称的所有部分。

不同的程序集解析选项的效果显示在 混合名称解析 部分中的表格中,适用于简单类型名称和程序集限定的类型名称。

解析类型

如果 typeName 未指定程序集名称,则始终调用 typeResolver。 如果 typeName 指定程序集名称, typeResolver 则仅在成功解析程序集名称时调用。 如果 assemblyResolver 或标准程序集探测返回 nulltypeResolver 则不调用。

该方法 typeResolver 接收三个参数:

  • 要搜索的程序集,或者如果 null 不包含程序集名称,则为 typeName
  • 类型的简单名称。 对于嵌套类型,这是最外部的包含类型。 对于泛型类型,这是泛型类型的简单名称。
  • 一个布尔值,如果忽略类型名称的大小写则为 true

实现确定使用这些参数的方式。 typeResolver如果方法无法解析类型,则该方法应返回null。 如果typeResolver返回nullthrowOnErrortrue,则GetType的此重载将引发TypeLoadException

对于简单和程序集限定的类型名称,不同类型解析选项的效果会显示为混合名称解析部分中的表。

解析嵌套类型

如果 typeName 为嵌套类型,则仅将最外层包含类型的名称传递给 typeResolver。 当typeResolver返回此类型时,GetNestedType方法以递归方式调用,直到最内部的嵌套类型被解析。

解析泛型类型

GetType 递归方式调用它以解析泛型类型:首先解析泛型类型本身,然后解析其类型参数。 如果类型参数是泛型的, GetType 则以递归方式调用以解析其类型参数,依此类推。

你提供的组合assemblyResolvertypeResolver必须能够解析此递归的所有级别。 例如,假设提供一个用于控制 assemblyResolver 加载的 MyAssembly。 假设你想要解析泛型类型 Dictionary<string, MyType>Dictionary(Of String, MyType) 在 Visual Basic 中)。 可能会传递以下泛型类型名称:

"System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]"

请注意, MyType 这是唯一的程序集限定类型参数。 Dictionary<TKey,TValue>String 类的名称都不是程序集限定的。 typeResolver 必须能处理程序集或 null,因为它将为 nullDictionary<TKey,TValue> 接收 String。 它可以通过调用一个接受字符串作为参数的 GetType 方法重载来处理这种情况,因为两个未限定的类型名称都位于 mscorlib.dll/System.Private.CoreLib.dll中。

Type t = Type.GetType(test,
                      (aName) => aName.Name == "MyAssembly" ?
                          Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") : null,
                      (assem, name, ignore) => assem == null ?
                          Type.GetType(name, false, ignore) :
                              assem.GetType(name, false, ignore)
                     );
let t =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else null),
        fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr))

不会为字典类型和字符串类型调用assemblyResolver方法,因为这些类型名称不是程序集限定的。

现在假设不是System.String,而是YourType作为第一个泛型参数类型,来自YourAssembly

"System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]"

由于此程序集既不是 mscorlib.dll/System.Private.CoreLib.dll,也不是当前正在执行的程序集,因此不能在没有程序集限定名称的情况下解析 YourTypeassemblyResolve 将以递归方式被调用,因此它必须能够处理这种情况。 现在,它使用提供的null对象来执行程序集加载,而不是为不同于MyAssembly的程序集返回AssemblyName

Type t2 = Type.GetType(test,
                       (aName) => aName.Name == "MyAssembly" ?
                           Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") :
                           Assembly.Load(aName),
                       (assem, name, ignore) => assem == null ?
                           Type.GetType(name, false, ignore) :
                               assem.GetType(name, false, ignore), true
                      );
let t2 =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else Assembly.Load aName),
        (fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr)), true)

解析具有特殊字符的类型名称

某些字符在程序集限定名称中具有特殊含义。 如果简单类型名称包含这些字符,则当简单名称是程序集限定名称的一部分时,这些字符会导致分析错误。 若要避免分析错误,必须使用反斜杠转义特殊字符,然后才能将程序集限定名称传递给 GetType 方法。 例如,如果一个类型被命名为Strange]Type,则必须在方括号之前添加转义字符,如下所示:Strange\]Type

注释

不能在 Visual Basic 或 C# 中创建具有此类特殊字符的名称,但可以使用公共中间语言(CIL)或发出动态程序集来创建。

下表显示了类型名称的特殊字符。

字符 含义
, (逗号) 程序集限定名称的分隔符。
[] (方括号) 作为后缀对,指示数组类型;作为分隔符对,将泛型参数列表和程序集限定的名称括起来。
&(与号) 指示类型为引用类型的后缀。
* (星号) 指示类型为指针类型的后缀。
+(加号) 嵌套类型的分隔符。
\ (反斜杠) 转义字符。

AssemblyQualifiedName 等属性会返回正确转义的字符串。 必须将正确转义的字符串传递给 GetType 方法。 反过来,GetType 方法会将正确转义的名称传递给 typeResolver 以及默认类型解析方法。 如果需将名称与 typeResolver 中的未转义名称进行比较,则必须删除转义字符。

混合名称解析

下表汇总了在assemblyResolvertypeResolver 和默认名称解析之间针对 typeName 中类型名称与程序集名称的所有组合的交互。

类型名称的内容 程序集解析程序方法 类型解析程序方法 结果
类型、组装 Null Null 等效于调用 Type.GetType(String, Boolean, Boolean) 方法重载。
类型、组装 已提供 Null assemblyResolver 返回程序集,否则在无法解析程序集时返回 null。 如果解析程序集,则 Assembly.GetType(String, Boolean, Boolean) 方法重载用于从程序集加载类型;否则,不会尝试解析该类型。
类型、组装 Null 已提供 等效于将程序集名称转换为对象 AssemblyName 并调用 Assembly.Load(AssemblyName) 方法重载来获取程序集。 如果程序集已解析,则会传递给 typeResolver;否则,不会调用 typeResolver,并且不会进一步尝试解析该类型。
类型、组装 已提供 已提供 assemblyResolver 返回程序集,否则在无法解析程序集时返回 null。 如果程序集已解析,则会传递给 typeResolver;否则,不会调用 typeResolver,并且不会进一步尝试解析该类型。
类型 null,已提供 Null 等效于调用 Type.GetType(String, Boolean, Boolean) 方法重载。 由于未提供程序集名称,因此只搜索 mscorlib.dll/System.Private.CoreLib.dll 和当前正在执行的程序集。 如果 assemblyResolver 已提供,则忽略它。
类型 null,已提供 已提供 typeResolver 被调用,并且 null 被传递给程序集。 typeResolver 可以从任何程序集提供类型,包括它为此加载的程序集。 如果 assemblyResolver 已提供,则忽略它。
集会 null,已提供 null,已提供 抛出 FileLoadException,因为程序集名称被解析得似乎是程序集限定的类型名称。 这会导致程序集名称无效。