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

Reply via email to