I create a dynamic method, i.e.:
class MyClass
{
private void object _o = <whatever>;
void CreateDynamicMethod()
{
DynamicMethod dm = new DynamicMethod("Test", ...);
// emit various IL
// need to push _o onto stack here
}
}
The 2nd comment, I want to push the value of _o currently onto the stack. I don't want to push the reference of _o as it will change as I build the dynamic method.
So lets say _o = 5, I want to push the 5, if _o contains a List, I want to push that, if it contains a string, I want to push the string.
The dynamic method (Test) is a static method and its obviously not going to have the this pointer of MyClass to get the field. I can't even put it in a static variable as that will be accessed during the execution of Test() and not while I'm building the method.
Even if I had the this pointer, the _o is not going to have the right value at Test() execution time.
Any suggestions?
You cannot pass a pointer because it will be invalid. However, you can pass in a handle. One technique I used in the past is to push an integer value onto the stack as an index into some statically-available resource (like a dictionary in a static class, or a network resource, or whatever) which will hold the value of the object at the future time the method will be needing it.
This is how the compiler does virtual method calls by the way. It doesn't know which version of an instance method it will call at compile time - it has no idea. So a token representing the method is pushed onto the stack instead of a pointer to the method itself. That token will then be used to do a vtable lookup at runtime using a resource at a well known location with the token as an index into that resource.
All you need to pull off your task is your own version of a vtable, and you'll use an integer as the token. Ldc.i4.s is the IL instruction to push any integer constant you want onto the stack. That's your token :) Push it onto the stack before calling a static method to retrieve your object.
Be sure to store the object before the method is called though ;)
There are ways to manipulate the stack to store a serialized proxy object that the method could then deserialize when it is called. But I'll get flamed if I explain how here.