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 Type
s and MethodInfo
s, not TypeBuilder
s and MethodBuilder
s.
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