Hi!

I cant understand, what I need to do to create generic type, emit
creating and emit generic method call of newly created type. In my
case I need to create delegate to generic method.
My steps:

   Create TypeDefinition of delegate extends MulticastDelegate

            // Create new delegate type
            var dlgtype = new
TypeDefinition(method.DeclaringType.Namespace, method.Name +
"_Delegate", TypeAttributes.Sealed | TypeAttributes.NestedAssembly,
_MulticastDelegate);

            delegateClass.NestedTypes.Add(dlgtype);

   Copy all GenericParams from method to newly created TypeDefinition

            if(method.DeclaringType.HasGenericParameters)
            {
                method.DeclaringType.CopyGenericParametersTo(dlgtype);
            }

   Create .ctor

            var constructor = new MethodDefinition(".ctor",
MethodAttributes.Public | MethodAttributes.CompilerControlled |
MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
MethodAttributes.HideBySig, _Void);
            dlgtype.Methods.Add(constructor);
            constructor.Parameters.Add(new
ParameterDefinition("'object'", ParameterAttributes.None, _Object));
            constructor.Parameters.Add(new
ParameterDefinition("'method'", ParameterAttributes.None, _IntPtr));
            constructor.IsRuntime = true;

   Create BeginInvoke using parameters types map (generic params from
original method to generic params from delegate type)
            var begininvoke = new MethodDefinition("BeginInvoke",
methodAttributes, _IAsyncResult);
            dlgtype.Methods.Add(begininvoke);
            foreach(var para in template.Parameters)
            {
                if (!para.ParameterType.IsGenericParameter)
                {
                    begininvoke.Parameters.Add(new
ParameterDefinition(para.Name, para.Attributes, para.ParameterType));
                }
                else
                {
                    var type =
dlgtype.GenericParameters.FirstOrDefault(p => p.Name ==
para.ParameterType.Name);
                    if(type != null)
                    {
                        begininvoke.Parameters.Add(new
ParameterDefinition(para.Name, para.Attributes, type));
                    }
                }
            }
            begininvoke.Parameters.Add(new
ParameterDefinition("callback", ParameterAttributes.None,
_AsyncCallback));
            begininvoke.Parameters.Add(new
ParameterDefinition("object", ParameterAttributes.None, _Object));
            begininvoke.IsRuntime = true;
   Create Iinvoke method
            // ...

Emit something like this:
            worker.InsertBefore(fst,
Instruction.Create(target.HasThis ? OpCodes.Ldarg_0 :
OpCodes.Ldnull));
            worker.InsertBefore(fst, Instruction.Create(OpCodes.Ldftn,
duplicate));
            worker.InsertBefore(fst,
Instruction.Create(OpCodes.Newobj, constructor));
            worker.InsertBefore(fst, Instruction.Create(OpCodes.Stloc,
dupdlg));
to create delegate


BUT. When I try to create delegate, I get System.TypeLoadException.
What's wrong?

Thanks.

-- 
--
mono-cecil

Reply via email to