本文提供了此 API 参考文档的补充说明。
可以使用 DynamicMethod 该类在运行时生成和执行方法,而无需生成动态程序集和动态类型来包含该方法。 当 DynamicMethod 对象被回收时,由即时 (JIT) 编译器创建的可执行代码也会被回收。 动态方法是生成和执行少量代码的最有效方法。
动态方法可以匿名托管,也可以与模块或类型在逻辑上关联。
如果动态方法是匿名托管的,则它位于系统提供的程序集中,因此与其他代码隔离。 默认情况下,它无权访问任何非公共数据。 匿名托管的动态方法可以受限地跳过 JIT 编译器的可见性检查(如果已向 JIT 编译器授予ReflectionPermissionReflectionPermissionFlag.RestrictedMemberAccess标志)。 动态方法访问其非公共成员的程序集的信任级别必须与发出该动态方法的调用堆栈的信任级别相同,或者是其子集。 有关动态方法的匿名托管的更多信息,请参阅演练:在部分信任场景中生成代码。
如果动态方法与指定的模块相关联,则动态方法将有效地全局到该模块。 它可以访问模块中的所有类型以及
internal
所有类型(Friend
在 Visual Basic 中)成员。 可以将动态方法与任何模块关联,无论该模块是否由你创建,只要调用栈中包含你的代码,且该调用栈能够满足带有 ReflectionPermission 标志的 RestrictedMemberAccess 需求即可。 如果授权中包含 ReflectionPermissionFlag.MemberAccess 标志,动态方法可以跳过 JIT 编译器的可见性检查,并访问模块中声明的所有类型或任何其他模块中声明的所有类型的专用数据。注释
指定与动态方法关联的模块时,该模块不得位于用于匿名托管的系统提供的程序集中。
如果动态方法与指定的类型相关联,则无论访问级别如何,它都有权访问该类型的所有成员。 此外,可以跳过 JIT 可见性检查。 这样,动态方法可以访问在同一个模块或任何程序集中的其他模块中声明的其他类型的私有数据。 可以将动态方法与任何类型关联,但代码必须同时授予 ReflectionPermission 以及 RestrictedMemberAccess 和 MemberAccess 标志。
下表显示了匿名托管的动态方法可以访问哪些类型和成员(有和没有 JIT 可见性检查),具体取决于是否授予带有 ReflectionPermission 标志的 RestrictedMemberAccess。
可见性检查 | 没有 RestrictedMemberAccess |
使用 RestrictedMemberAccess |
---|---|---|
不跳过 JIT 可见性检查 | 任何程序集中的公共类中的公共成员。 | 任何程序集中的公共类中的公共成员。 |
跳过 JIT 可见性检查,但有一定限制。 | 任何程序集中的公共类中的公共成员。 | 所有类型的所有成员,仅在信任级别等于或低于调用动态方法的程序集的信任级别的程序集中可用。 |
下表显示了与模块或模块中的类型关联的动态方法可访问哪些类型和成员。
跳过 JIT 可见性检查 | 与模块关联 | 与类型关联 |
---|---|---|
否 | 模块中公共类型、内部类型和私有类型的公共成员和内部成员。 任何程序集中的公共类中的公共成员。 |
关联类型的所有成员。 模块中所有其他类型的公共成员和内部成员。 任何程序集中的公共类中的公共成员。 |
是的 | 任何程序集中所有类型的所有成员。 | 任何程序集中所有类型的所有成员。 |
与模块关联的动态方法具有该模块的权限。 与类型关联的动态方法具有包含该类型的模块的权限。
动态方法及其参数不必命名,但可以指定名称来帮助调试。 动态方法或其参数不支持自定义属性。
尽管动态方法是 static
方法(Shared
Visual Basic 中的方法),但委托绑定的宽松规则允许动态方法绑定到对象,以便它在使用该委托实例调用时类似于实例方法。 为CreateDelegate(Type, Object)方法重载提供了一个示例以进行演示。
验证
以下列表汇总了动态方法可以包含不可验证的代码的条件。 例如,如果动态方法的InitLocals属性设置为false
,则该方法是不可验证的。
- 与安全关键程序集关联的动态方法也是安全关键型方法,可以跳过验证。 例如,一个没有安全属性但作为桌面应用程序运行的程序集会被运行时视为安全关键。 如果将动态方法与程序集相关联,则动态方法可以包含无法验证的代码。
- 如果包含不可验证代码的动态方法与具有级别 1 透明度的程序集相关联,则实时 (JIT) 编译器会注入安全需求。 仅当动态方法由完全受信任的代码执行时,需求才会成功。 请参阅 Security-Transparent 代码(级别 1)。
- 如果包含不可验证代码的动态方法与具有级别 2 透明度(如 mscorlib.dll)的程序集相关联,则会引发异常(由 JIT 编译器注入),而不是发出安全要求。 请参阅 Security-Transparent 代码编号,级别 2。
- 包含不可验证代码的匿名托管动态方法始终引发异常。 它永远不能跳过验证,即使它是由完全受信任的代码创建和执行的。
为不可验证的代码引发的异常因调用动态方法的方式而异。 如果使用从 CreateDelegate 方法返回的委托调用动态方法,则会引发 VerificationException。 如果通过 Invoke 方法调用动态方法,则会抛出一个 TargetInvocationException,其中包含一个内部 VerificationException。