【问题标题】:Create a constructor call using Reflection Emit that passes a Func<> as a parameter使用将 Func<> 作为参数传递的反射发射创建构造函数调用
【发布时间】:2013-05-07 12:19:52
【问题描述】:

我希望有人可以为我指出以下问题的正确方向。

我正在开发一个使用 Reflection.Emit 生成类型的项目,一切正常,直到出现需要将 Func 传递给新对象的构造函数的要求,如下所示。

public class SearchTerm : IEntity
{
   private readonly NavigationProperty<Item> _item;

   public SearchTerm()
   {
       _item = new NavigationProperty<Item>(() => ItemIds);
   }
   public string[] ItemIds { get; set; }
}

使用 Linqpad 我可以看到 IL 输出如下:

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  

我的问题是我不确定如何在 IL 中定义委托。

我已经尝试了以下

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);

然后尝试创建以下委托会引发“不支持的异常”,并出现错误“派生类必须提供实现。”

var funcType = typeof(Func<,>).MakeGenericType(typeBuilder, typeof(IEnumerable<string>));
method.CreateDelegate(funcType);

我也尝试过使用 Delegate.CreateDelegate 和 DynamicMethod,它们都需要在使用之前创建类型。

非常感谢任何关于我可能做错的建议。

【问题讨论】:

    标签: c# reflection delegates reflection.emit


    【解决方案1】:

    如果你想调用你的代码,你必须使用Types 和MethodInfos,而不是TypeBuilders 和MethodBuilders。

    所以,你需要 CreateType() 然后使用 Type 及其方法:

    var generatedType = typeBuilder.CreateType();
    
    var funcType = typeof(Func<,>).MakeGenericType(
        generatedType, typeof(IEnumerable<string>));
    var d = generatedType.GetMethod("func").CreateDelegate(funcType);
    

    【讨论】:

    • 所以在获得实际类型之前不能创建委托?只是为了确认我当前使用 typebuilder 生成的 Class SearchTerm 不能包含 _item = new NavigationProperty(() => ItemIds);因为我需要调用 createType 来使用委托中类的属性。顺便说一句,感谢您的回复
    • @SCB 我不明白您为什么需要创建委托的实例来生成该代码。您需要生成代码来创建委托,而不仅仅是创建委托。
    • 好的,但是我的 SearchTerm 构造函数创建了一个新的 NavigationProperty,我需要将一些内容传递给该对象的构造函数调用。
    • @SCB 是的,但是您需要生成执行此操作的代码,您不需要实际调用CreateDelegate() 来执行此操作。你应该做什么: 1.创建“匿名”方法(实际上是一个普通的方法,IL中没有匿名方法)。 2. 使用ldftn yourMethodnewobj Func&lt;GeneratedType, IEnumerable&lt;string&gt;&gt; 生成创建委托的代码。
    猜你喜欢
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    相关资源
    最近更新 更多