System.Reflection.Emit.DynamicMethod 类

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

可以使用 DynamicMethod 该类在运行时生成和执行方法,而无需生成动态程序集和动态类型来包含该方法。 回收对象时 DynamicMethod ,将回收由实时 (JIT) 编译器创建的可执行代码。 动态方法是生成和执行少量代码的最有效方法。

动态方法可以匿名托管,也可以与模块或类型在逻辑上关联。

  • 如果动态方法是匿名托管的,则它位于系统提供的程序集中,因此与其他代码隔离。 默认情况下,它无权访问任何非公共数据。 如果已向 JIT 编译器授予ReflectionPermissionReflectionPermissionFlag.RestrictedMemberAccess标志,匿名托管动态方法可以限制跳过 JIT 编译器的可见性检查。 由动态方法访问其非公共成员的程序集的信任级别必须等于发出动态方法的调用堆栈的信任级别或子集。 有关匿名托管的动态方法的详细信息,请参阅 演练:在部分信任方案中发出代码。

  • 如果动态方法与指定的模块相关联,则动态方法将有效地全局到该模块。 它可以访问模块中的所有类型以及 internal 所有类型(Friend 在 Visual Basic 中)成员。 无论是否创建了模块,都可以将动态方法与任何模块相关联,前提是包含代码的调用堆栈可以满足对RestrictedMemberAccess标志的需求ReflectionPermissionReflectionPermissionFlag.MemberAccess如果授权中包含该标志,动态方法可以跳过 JIT 编译器的可见性检查,并访问模块中声明的所有类型的私有数据,或者在任何程序集中声明的任何其他模块中。

    注意

    指定与动态方法关联的模块时,该模块不得位于用于匿名托管的系统提供的程序集中。

  • 如果动态方法与指定的类型相关联,则无论访问级别如何,它都有权访问该类型的所有成员。 此外,可以跳过 JIT 可见性检查。 这样,动态方法可以访问在同一模块或任何程序集中声明的其他任何模块中声明的其他类型的私有数据。 可以将动态方法与任何类型相关联,但代码必须同时授予 ReflectionPermissionRestrictedMemberAccess 代码和 MemberAccess 标志。

下表显示了匿名托管的动态方法可以访问哪些类型和成员,无论是否授予标志RestrictedMemberAccess,以及没有 JIT 可见性检查ReflectionPermission

可见性检查 没有 RestrictedMemberAccess With RestrictedMemberAccess
不跳过 JIT 可见性检查 任何程序集中公共类型的公共成员。 任何程序集中公共类型的公共成员。
跳过 JIT 可见性检查,但存在限制 任何程序集中公共类型的公共成员。 所有类型的所有成员,仅在其信任级别等于或小于发出动态方法的程序集的信任级别中。

下表显示了与模块或模块中的类型关联的动态方法可访问哪些类型和成员。

跳过 JIT 可见性检查 与模块关联 与类型关联的
模块中公共、内部和专用类型的公共成员和内部成员。

任何程序集中公共类型的公共成员。
关联类型的所有成员。 模块中所有其他类型的公共成员和内部成员。

任何程序集中公共类型的公共成员。
任何程序集中所有类型的所有成员。 任何程序集中所有类型的所有成员。

与模块关联的动态方法具有该模块的权限。 与类型关联的动态方法具有包含该类型的模块的权限。

动态方法及其参数不必命名,但可以指定名称来帮助调试。 动态方法或其参数不支持自定义属性。

尽管动态方法是 static 方法(Shared Visual Basic 中的方法),但委托绑定的宽松规则允许动态方法绑定到对象,以便它在使用该委托实例调用时类似于实例方法。 演示此方法 CreateDelegate(Type, Object) 重载的示例。

验证

以下列表汇总了动态方法可以包含不可验证的代码的条件。 (例如,如果 InitLocals 动态方法的属性设置为 false.)

  • 与安全关键程序集关联的动态方法也是安全关键型方法,可以跳过验证。 例如,没有作为桌面应用程序运行的安全属性的程序集被运行时视为安全关键。 如果将动态方法与程序集相关联,则动态方法可以包含无法验证的代码。
  • 如果包含不可验证代码的动态方法与具有级别 1 透明度的程序集相关联,则实时 (JIT) 编译器会注入安全需求。 仅当动态方法由完全受信任的代码执行时,需求才会成功。 请参阅 安全透明代码级别 1
  • 如果包含不可验证代码的动态方法与具有级别 2 透明度(如 mscorlib.dll)的程序集相关联,则会引发异常(由 JIT 编译器注入),而不是发出安全要求。 请参阅 安全透明代码级别 2
  • 包含不可验证代码的匿名托管动态方法始终引发异常。 它永远不能跳过验证,即使它是由完全受信任的代码创建和执行的。

为不可验证的代码引发的异常因调用动态方法的方式而异。 如果使用从 CreateDelegate 该方法返回的委托调用动态方法,则会引发一个 VerificationException 。 如果使用该方法调用动态方法 InvokeTargetInvocationException 则会引发内部 VerificationException方法。