I'm hoping someone can point me in the right direction with the following problem.
I am working on a project where the types are generated using Reflection.Emit, all has been working fine until a requirement arose where I needed to pass a Func<> into a constructor of a new object as below.
public class SearchTerm : IEntity
{
private readonly NavigationProperty<Item> _item;
public SearchTerm()
{
_item = new NavigationProperty<Item>(() => ItemIds);
}
public string[] ItemIds { get; set; }
}
Using Linqpad I can see the IL output is as follows:
SearchTerm.<.ctor>b__0:
IL_0000: ldarg.0
IL_0001: call UserQuery+SearchTerm.get_ItemIds
IL_0006: stloc.0 // CS$1$0000
IL_0007: br.s IL_0009
IL_0009: ldloc.0 // CS$1$0000
IL_000A: ret
SearchTerm..ctor:
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: call System.Object..ctor
IL_0008: nop
IL_0009: nop
IL_000A: ldarg.0
IL_000B: ldloc.0
IL_000C: brtrue.s IL_001D
IL_000E: ldarg.0
IL_000F: ldftn UserQuery+SearchTerm.<.ctor>b__0
IL_0015: newobj System.Func<System.Collections.Generic.IEnumerable<System.String>>..ctor
IL_001A: stloc.0
IL_001B: br.s IL_001D
IL_001D: ldloc.0
IL_001E: newobj UserQuery<UserQuery+Item>+NavigationProperty`1..ctor
IL_0023: stfld UserQuery+SearchTerm._item
IL_0028: nop
IL_0029: ret
The problem I have is that I'm not sure how to define the delegate within IL.
I have tried the following
var method = typeBuilder.DefineMethod("func", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(IEnumerable<string>), Type.EmptyTypes);
var methodIl = method.GetILGenerator();
methodIl.Emit(OpCodes.Ldarg_0);
methodIl.Emit(OpCodes.Call, dictionary["get_ItemIds"]);
methodIl.Emit(OpCodes.Ret);
Then trying to create the delegate the following throws "Not Supported Exception" with the error "Derived classes must provide an implementation."
var funcType = typeof(Func<,>).MakeGenericType(typeBuilder, typeof(IEnumerable<string>));
method.CreateDelegate(funcType);
I have also tried using Delegate.CreateDelegate and DynamicMethod which both require the type to have been created before using them.
Any suggestion on what I might be doing wrong are greatly appreciated.
If you want to invoke your code, you have to work with Types and MethodInfos, not TypeBuilders and MethodBuilders.
So, you need to CreateType() and then use that Type and its method:
var generatedType = typeBuilder.CreateType();
var funcType = typeof(Func<,>).MakeGenericType(
generatedType, typeof(IEnumerable<string>));
var d = generatedType.GetMethod("func").CreateDelegate(funcType);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With