1

动态方法能否像普通方法或代码一样工作,因为它可以访问通常可以访问变量的变量、调用方法和初始化变量(当然是在方法的范围内)?

我见过的唯一例子是它被传递了一些参数并返回一些值,并且没有改变它之外的任何变量。

我说的是 System.Reflection.Emit.DynamicMethod 类。我很难理解它,因为需要使用我还不太了解的 MSIL。

4

1 回答 1

1

是的。DynamicMethod 可以附加到一个类,在这种情况下,它可以访问类私有静态字段(如果 DynamicMethod 是实例方法,则可能访问类私有字段,但我不记得这是否是受支持的方案)。它还可以访问在其中创建 DynamicMethod 的程序集内部的程序集内部方法、属性和类型。

您使用动态方法的场景是什么?

我有一些关于动态编程的博客文章,包括一些关于在我的博客上使用 DynamicMethod 类的条目:http ://robpaveza.net/tag/dynamic-programming 。具体来说,这篇文章讲的是如何计算文件修订证明,你可以在这里看到结果实现(显然,我没有写过第 2 部分,但我链接的 BN# 中的实现是分析的结果)。

让我带您了解 Compile 方法:

  1. 类型 parameterType = typeof(uint).MakeByRefType()

最后一个方法是取出uint参数;此行获取对 uint-ref 运行时类型的引用。如果我用普通的 C# 编写方法声明,它将如下所示:

public static void CheckRevision(out uint a, out uint b, out uint c, out uint s);

38-40。foreach(公式中的字符串公式) CompileStandardFormula(生成器,公式)

正如我在我的博客文章中提到的那样,我所做的数学总是以以下形式提供:

A=A-S B=B-C C=C+A A=A+B

其中 A、B 和 C 是状态变量,S 是输入(文件中的下一个 uint 值)。

CompileStandardFormula 函数发出 IL 计算所示四个操作中的一个单独操作的逻辑。回想一下,CLR 是一个基于堆栈的状态机,数学运算发生在堆栈上的值被弹出和结果被压入的情况下。因此,例如,对于 A=AS,将发出以下 IL:

ldarg.0  // push &A, which is a reference to the location that actually contains the value of A
ldarg.0  // push &A
ldind.u4 // dereference the top-most value on the stack, which puts the actual value of &A ready for operation
ldarg.3  // push &S
ldind.u4 // dereference &S
sub      // subtracts [stack-1] from [stack-2], which effectively is A-S
stind.u4 // remember the first ldarg.0? That's getting accessed now and the subtraction result is going there

所以,在这一点上,应该很容易弄清楚:我的 DynamicMethod 编译了更新文件中单次传递的所有状态变量所需的数学运算。在发出所有 IL 之后,因为我们知道堆栈的状态上没有任何内容(无论如何,比方法进入时更多),我们可以抛出一个快速的“ret”指令,我们就完成了。

无论如何,希望这会有所帮助。

于 2013-01-13T01:04:51.800 回答