user1594138
user1594138

Reputation: 1011

Can a DynamicMethod access variables outside of it?

Can a Dynamic Method work like a normal method or code, in that it can access variables where variables can normally be accessed, call methods, and initialize variables (of course in the scope of the method)?

The only examples I've seen is where it is passed some parameters and returns some value and does nothing to change any variables outside of it.

I'm talking about the System.Reflection.Emit.DynamicMethod class. I'm having trouble understanding it since one needs to use MSIL which I don't know much of yet.

Upvotes: 1

Views: 226

Answers (1)

Rob
Rob

Reputation: 3516

Yes. A DynamicMethod can be attached to a class, in which case it can access class-private static fields (and possibly class-private fields if the DynamicMethod is an instance method, but I don't recall whether that's a supported scenario). It can also access assembly-internal methods, properties, and types that are internal to the assembly in which the DynamicMethod is created.

What's the scenario you're using dynamic methods for?

I have some blog articles about dynamic programming, including a couple entries about using the DynamicMethod class on my blog: http://robpaveza.net/tag/dynamic-programming . Specifically, this article talks about how to calculate a file revision proof, and you can see the result implementation here (evidently, I never wrote part 2, but the implementation in BN# that I linked was the result of the analysis).

Let me walk you through the Compile method:

  1. Type parameterType = typeof(uint).MakeByRefType()

The final method is going to take out uint parameters; this line obtains a reference to the uint-ref runtime type. The method declaration would look like this if I were to write it in normal C#:

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

38-40. foreach (string formula in formulas) CompileStandardFormula(generator, formula)

As I mention in my blog post about it, the math that I do is always provided in the form of:

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

Where A, B, and C are state variables and S is an input (the next uint value from the file).

The CompileStandardFormula function emits the IL that computes the logic for one individual operation of the four shown. Recall that the CLR is a stack-based state machine, and math operations occur with the values on the stack being popped and results being pushed. So, for A=A-S, for example, the following IL is what would be emitted:

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

So, at this point, it should be pretty easy to figure out: my DynamicMethod compiles the math operation required to update all state variables for a single pass in the file. After all of the IL is emitted, because we know the state of the stack has nothing on it (more than when the method entered, anyway), we can just throw out a quick 'ret' instruction and we're done.

Anyway, hope this is helpful.

Upvotes: 1

Related Questions