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