I want to create a Comparison<>-Delegate via reflection in code. I have this:
var returnType = typeof (Int32);
var parameters = typeof(Comparison<>).GetMethod("Invoke").GetParameters().Select(x => x.ParameterType).ToArray();
AppDomain domain = AppDomain.CurrentDomain;
AssemblyName aname = new AssemblyName("MyEmissions");
AssemblyBuilder assemBuilder = domain.DefineDynamicAssembly(aname, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder modBuilder = assemBuilder.DefineDynamicModule("MainModule", "MyEmissions.dll");
TypeBuilder tb = modBuilder.DefineType("Widget", TypeAttributes.Public);
MethodBuilder mb = tb.DefineMethod("Echo", MethodAttributes.Public | MethodAttributes.Static);
mb.SetSignature(returnType, null, null, parameters, null, null);
ILGenerator gen = mb.GetILGenerator();
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Ret);
var foo = MulticastDelegate.CreateDelegate(typeof(Comparison<>), mb);
The last line throws a ArgumentException: MethodInfo must be a runtime MethodInfo object. I'm new to reflection and emit and have a feeling that only a small step is missing!?
Edit:
I'm not bound to creating a new Assembly - I also tried DynamicMethod:
var returnType = typeof (Int32);
var parameters = typeof(Comparison<>).GetMethod("Invoke").GetParameters().Select(x => x.ParameterType).ToArray();
var handler = new DynamicMethod("", returnType, parameters);
var generator = handler.GetILGenerator();
foreach (var parameter in parameters)
{
var localVariable = generator.DeclareLocal(parameter);
generator.Emit(OpCodes.Ldloc, localVariable);
}
if (returnType != null)
{
var returnValue = generator.DeclareLocal(returnType);
generator.Emit(OpCodes.Ldloc, returnValue);
}
generator.Emit(OpCodes.Ret);
handler.CreateDelegate(typeof(Comparison<>));
Throws a BadImageFormatException :/
Solution:
var returnType = typeof (Int32);
var methodParameters = typeof(Comparison<>).GetMethod("Invoke").GetParameters().Select(x => x.ParameterType.ToString()).ToArray();
AppDomain domain = AppDomain.CurrentDomain;
AssemblyName aname = new AssemblyName("MyEmissions");
AssemblyBuilder assemBuilder = domain.DefineDynamicAssembly(aname, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder modBuilder = assemBuilder.DefineDynamicModule("MainModule", "MyEmissions.dll");
TypeBuilder tb = modBuilder.DefineType("Widget", TypeAttributes.Public);
MethodBuilder mb = tb.DefineMethod("Echo", MethodAttributes.Public | MethodAttributes.Static);
GenericTypeParameterBuilder[] typeParameters = mb.DefineGenericParameters(methodParameters);
mb.SetReturnType(returnType);
mb.SetParameters(typeParameters);
ILGenerator gen = mb.GetILGenerator();
gen.Emit(OpCodes.Ldnull);
gen.Emit(OpCodes.Ret);
var dt = tb.CreateType();
var mi = dt.GetMethod("Echo");
var gm = mi.MakeGenericMethod(new[] { typeof(string), typeof(string) });
var parameter = MulticastDelegate.CreateDelegate(typeof(Comparison<string>), gm);