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
参数中提供程序集。 在混合名称解析部分中,包括或省略不同类型名称解析的程序集名称的效果显示为表。
常规用法说明:
不要将
assemblyResolver
方法传递给或typeResolver
来自未知或不受信任的调用方的方法。 仅使用你提供或者熟悉的方法。注意
使用未知或不受信任的调用方的方法可能会导致恶意代码特权提升。
如果省略
assemblyResolver
和/或typeResolver
参数,则参数的值throwOnError
将传递给执行默认解析的方法。如果是
throwOnError
,此方法将TypeLoadException引发返回null
时间typeResolver
,返回FileNotFoundException时间assemblyResolver
null
。true
此方法不捕获由
assemblyResolver
和typeResolver
引发的异常。 你负责解析程序方法引发的任何异常。
解析程序集
该方法 assemblyResolver
接收一个 AssemblyName 对象,该对象是通过分析包含在 typeName
其中的字符串程序集名称生成的。 如果 typeName
不包含程序集名称, assemblyResolver
则不调用并 null
传递给 typeResolver
。
如果未 assemblyResolver
提供,则使用标准程序集探测来查找程序集。 如果 assemblyResolver
已提供,则 GetType 该方法不执行标准探测;在这种情况下,必须确保 assemblyResolver
可以处理传递给它的所有程序集。
如果无法解析程序集,该方法 assemblyResolver
应返回 null
。 如果返回,则不调用,不会进一步处理;此外,如果是throwOnError
true
,则会引发 aFileNotFoundException。 typeResolver
null
assemblyResolver
AssemblyName如果传递给assemblyResolver
的是部分名称,则其一个或多个部分为 null
。 例如,如果它没有版本,则 Version 属性为 null
. Version如果属性、CultureInfo属性和GetPublicKeyToken方法全部返回null
,则只提供程序集的简单名称。 该方法 assemblyResolver
可以使用或忽略程序集名称的所有部分。
不同程序集解析选项的效果显示为混合名称解析部分中的表,用于简单类型名称和程序集限定的类型名称。
解析类型
如果未 typeName
指定程序集名称, typeResolver
则始终调用。 如果 typeName
指定程序集名称, typeResolver
则仅在成功解析程序集名称时调用。 如果 assemblyResolver
或标准程序集探测返回 null
, typeResolver
则不调用。
该方法 typeResolver
接收三个参数:
- 要搜索的程序集,或者
null
不包含typeName
程序集名称。 - 类型的简单名称。 对于嵌套类型,这是最外部的包含类型。 对于泛型类型,这是泛型类型的简单名称。
- 一个布尔值,表示
true
要忽略类型名称大小写。
实现确定使用这些参数的方式。 typeResolver
如果方法无法解析类型,则该方法应返回null
。 如果返回并且是,则此重载GetType将引发 aTypeLoadException。true
throwOnError
null
typeResolver
对于简单和程序集限定的类型名称,不同类型解析选项的效果显示为混合名称解析部分中的表。
解析嵌套类型
如果 typeName
为嵌套类型,则仅将最外层包含类型的名称传递给 typeResolver
。 返回此类型时 typeResolver
,该方法 GetNestedType 以递归方式调用,直到解析最内部的嵌套类型。
解析泛型类型
以 GetType 递归方式调用它以解析泛型类型:首先解析泛型类型本身,然后解析其类型参数。 如果类型参数是泛型的, GetType 则以递归方式调用以解析其类型参数,依此类推。
你提供的组合assemblyResolver
typeResolver
必须能够解析此递归的所有级别。 例如,假设你提供一个 assemblyResolver
控制加载的 MyAssembly
控件。 假设你想要解析泛型类型 Dictionary<string, MyType>
(Dictionary(Of String, MyType)
在 Visual Basic 中)。 可以传递以下泛型类型名称:
"System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]"
请注意, MyType
这是唯一的程序集限定类型参数。 和String类的名称Dictionary<TKey,TValue>不是程序集限定的。 你必须typeResolver
能够处理程序集,或者null
,因为它将接收并String接收null
Dictionary<TKey,TValue>。 它可以通过调用采用字符串的方法的 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也不是当前正在执行的程序集,因此不能在没有程序集限定名称的情况下解析 YourType
。 由于将以递归方式调用, assemblyResolve
因此它必须能够处理这种情况。 它现在使用提供AssemblyName的对象执行程序集加载,而不是为程序集MyAssembly
返回null
。
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
进行比较,则必须删除转义字符。
混合名称解析
下表汇总了类型名称和程序集名称typeName
的所有组合之间的typeResolver
assemblyResolver
交互以及默认名称解析:
类型名称的内容 | 程序集解析程序方法 | 类型解析程序方法 | Result |
---|---|---|---|
type、 assembly | Null | Null | 等效于调用 Type.GetType(String, Boolean, Boolean) 方法重载。 |
type、 assembly | 提供的 | Null | assemblyResolver 如果程序集无法解析程序集,则返回 null 该程序集。 如果解析程序集,则 Assembly.GetType(String, Boolean, Boolean) 方法重载用于从程序集加载类型;否则,不会尝试解析该类型。 |
type、 assembly | Null | 提供的 | 等效于将程序集名称转换为对象 AssemblyName 并调用 Assembly.Load(AssemblyName) 方法重载来获取程序集。 如果已解析程序集,则会传递给 typeResolver 该程序集;否则 typeResolver ,不会调用该程序集,并且不会进一步尝试解析类型。 |
type、 assembly | 提供的 | 提供的 | assemblyResolver 如果程序集无法解析程序集,则返回 null 该程序集。 如果已解析程序集,则会传递给 typeResolver 该程序集;否则 typeResolver ,不会调用该程序集,并且不会进一步尝试解析类型。 |
type | null,提供 | Null | 等效于调用 Type.GetType(String, Boolean, Boolean) 方法重载。 由于未提供程序集名称,因此仅搜索mscorlib.dll/System.Private.CoreLib.dll和当前正在执行的程序集。 如果 assemblyResolver 已提供,则忽略它。 |
type | null,提供 | 提供的 | typeResolver 调用 并 null 传递程序集。 typeResolver 可以从任何程序集提供类型,包括它为此加载的程序集。 如果 assemblyResolver 已提供,则忽略它。 |
assembly | null,提供 | null,提供 | 引发 A FileLoadException ,因为程序集名称被分析为程序集限定的类型名称。 这会导致程序集名称无效。 |