I need to create delegates like this (all methods but
TryCatchFinallyBlock must be generated by Mono.Cecil):
/* Generated */
public delegate void TryCatchFinallyBlock_Delegate(object self,
object[] args);
/* Generated */
public static bool TestArgs(int x, int y, string str)
{
Delegate deleg1 = new
TryCatchFinallyBlock_Delegate(TryCatchFinnalyBlock);
Source.MethodBody();
Console.WriteLine("Real values: {0}, {1}, {2}", x, y, str);
return true;
}
private static void TryCatchFinnalyBlock(object self, object[] args)
{
...
}
My tasks are:
1) create delegate type by known method defenition;
2) Inject instructions to create delegate to TryCatchFinnalyBlock
3) do something with created delegate (may be call)
My code here:
public static void EmitCreateDelegateToLocalMethod(this ILProcessor
worker, MethodDefinition source, out VariableDefinition dlg, out
MethodDefinition ctor)
{
// Define some variables
var body = worker.Body;
var method = body.Method;
var module = body.Method.Module;
var newdlg = body.Variables.Add<Delegate>(module);
var multiDelegateType = module.Import(typeof(MulticastDelegate));
var voidType = module.Import(typeof(void));
var objectType = module.Import(typeof(object));
var nativeIntType = module.Import(typeof(IntPtr));
var asyncCallbackType = module.Import(typeof(AsyncCallback));
var asyncResultType = module.Import(typeof(IAsyncResult));
// Create new delegate type
var dlgtype = new TypeDefinition(method.DeclaringType.Namespace,
method.Name + "_Delegate" +
body.Method.DeclaringType.NestedTypes.Count, TypeAttributes.Sealed |
TypeAttributes.NestedAssembly | TypeAttributes.RTSpecialName,
multiDelegateType);
method.DeclaringType.NestedTypes.Add(dlgtype);
var constructor = new MethodDefinition(".ctor",
MethodAttributes.Public | MethodAttributes.CompilerControlled|
MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
MethodAttributes.HideBySig, voidType);
dlgtype.Methods.Add(constructor);
constructor.Parameters.Add(new ParameterDefinition("'object'",
ParameterAttributes.None, objectType));
constructor.Parameters.Add(new ParameterDefinition("'method'",
ParameterAttributes.None, nativeIntType));
//dlgtype. = true;
var begininvoke = new MethodDefinition("BeginInvoke",
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual, asyncResultType);
dlgtype.Methods.Add(begininvoke);
foreach(var para in source.Parameters)
{
begininvoke.Parameters.Add(new ParameterDefinition(para.Name,
para.Attributes, para.ParameterType));
}
begininvoke.Parameters.Add(new ParameterDefinition("callback",
ParameterAttributes.None, asyncCallbackType));
begininvoke.Parameters.Add(new ParameterDefinition("object",
ParameterAttributes.None, objectType));
var endinvoke = new MethodDefinition("EndInvoke",
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual, voidType);
dlgtype.Methods.Add(endinvoke);
endinvoke.Parameters.Add(new ParameterDefinition("result",
ParameterAttributes.None, asyncResultType));
var invoke = new MethodDefinition("Invoke", MethodAttributes.Public |
MethodAttributes.HideBySig | MethodAttributes.NewSlot |
MethodAttributes.Virtual, voidType);
dlgtype.Methods.Add(invoke);
foreach(var para in source.Parameters)
{
invoke.Parameters.Add(new ParameterDefinition(para.Name,
para.Attributes, para.ParameterType));
}
ctor = constructor;
dlg = newdlg;
}
After this I call my method:
VariableDefinition nsrgdlg;
MethodDefinition nsrgdlg_ctor;
worker.EmitCreateDelegateToLocalMethod(target, out nsrgdlg, out
nsrgdlg_ctor);
worker.InsertBefore(fst, Instruction.Create(OpCodes.Ldnull,
(object)null));
worker.InsertBefore(fst, Instruction.Create(OpCodes.Ldftn, target));
worker.InsertBefore(fst, Instruction.Create(OpCodes.Newobj,
nsrgdlg_ctor));
worker.InsertBefore(fst, Instruction.Create(OpCodes.Stloc, nsrgdlg));
But program launches with exception. What is wrong? How I should to
create delegates correctly?
thanks.
--
--
mono-cecil