If I create a DynamicMethod from inside a class method how can I call another method of my class from the DynamicMethod Delegate? I need somehow to capture the this reference in the DynamicMethod code. But I can't find an overladed version of ILGenerator.Emit which takes an object as parameter.
The code is so far:
void CallOpc(string name, object[] inp, object[] outp)
{
//...
}
public D CreateDelegate<D>(string opcName) where D : class
{
var dType = typeof(D);
var invoke = dType.GetMethod("Invoke");
var parameters = invoke.GetParameters();
var paramTypes = parameters.Select(p => p.ParameterType).ToArray();
DynamicMethod dm = new DynamicMethod(
opcName,
invoke.ReturnType,
paramTypes,
true);
var inp = parameters.Where(p => !p.IsOut).Select(p => p.ParameterType).ToList();
var outp = parameters.Where(p => p.IsOut).Select(p => p.ParameterType).ToList();
if (invoke.ReturnType != typeof(void))
{
outp.Insert(0, invoke.ReturnType);
}
ILGenerator il = dm.GetILGenerator();
LocalBuilder invar = il.DeclareLocal(typeof(object[]));
LocalBuilder outvar = il.DeclareLocal(typeof(object[]));
il.Emit(OpCodes.Ldc_I4, inp.Count);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Stloc, invar);
for (int i = 0; i < inp.Count; i++)
{
il.Emit(OpCodes.Ldloc, invar);
il.Emit(OpCodes.Ldc_I4, i);
int j = Array.IndexOf(paramTypes, inp[i]);
il.Emit(OpCodes.Ldarg, j);
if (!inp[i].IsClass)
{
il.Emit(OpCodes.Box, inp[i]);
}
il.Emit(OpCodes.Stelem_Ref);
}
il.Emit(OpCodes.Ldc_I4, outp.Count);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Stloc, outvar);
il.Emit(OpCodes.Ldarg_0); // <- push this on the evaluation stack ???
il.Emit(OpCodes.Ldstr, opcName);
il.Emit(OpCodes.Ldloc, invar);
il.Emit(OpCodes.Ldloc, outvar);
MethodInfo callOpcMeth = GetType().GetMethod("CallOpc", BindingFlags.Instance | BindingFlags.NonPublic);
il.Emit(OpCodes.Callvirt, callOpcMeth);
for (int o = 0; o < outp.Count; o++)
{
// TODO: handle out params and return value
}
il.Emit(OpCodes.Ret);
return (D)(object)dm.CreateDelegate(dType);
}
My problem is the line marked with ???
How to reference the
thispointer from aDynamicMethod?
At low level, methods do not have a specific this pointer, instead the first argument of the method is used as this.
To reference the this pointer, here is what you have to do:
thisthis wherever you wantDynamicMethod.CreateDelegate(Type,Object) to bind the first parameter to your object: return (D)(object)dm.CreateDelegate(dType, this);Note that creating dynamic methods is expensive. If you generate the same DynamicMethod for multiple instances, you should cache the method itself, and create delegates using the cached method, but with different target parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With