【问题标题】:CreateDelegate Derived classes must provide an implementationCreateDelegate 派生类必须提供实现
【发布时间】:2013-09-26 19:37:59
【问题描述】:

当调用创建编译表达式时,我试图在生成的编译委托上调用 CreateDelegate,但遇到 NotSupportedException,解释是:派生类必须提供实现。如何为已编译的方法创建委托?

public delegate int AddOne(int input);

void Main()
{
    var input = Expression.Parameter(typeof(int));
    var add = Expression.Add(input,Expression.Constant(1));
    var lambda = Expression.Lambda(typeof(AddOne),add,input);
    var compiled = (AddOne)lambda.Compile();
    compiled.Method.CreateDelegate(typeof(AddOne));
}

【问题讨论】:

  • 它仍然是真实的。我还需要获取已编译委托的 MethodInfo,将其保存在我的结构中,然后“重新转换”MethodInfo 以再次委托。此代码应该可以工作,但它不能工作,并且“派生类必须提供实现”错误的性质尚不清楚。

标签: c# .net reflection delegates linq-expressions


【解决方案1】:

您无需致电CreateDelegate。将结果从 lambda.Compile 转换为 AddOne 就是您所需要的。

观察:

public delegate int AddOne(int input);

public int Test(AddOne f)
{
   return f(1);
}

void Main()
{
    var input = Expression.Parameter(typeof(int));
    var add = Expression.Add(input,Expression.Constant(1));
    var lambda = Expression.Lambda(typeof(AddOne),add,input);
    var compiled = (AddOne)lambda.Compile();
    Console.WriteLine(Test(compiled)); // 2
}

您可以成功调用Test 方法,该方法接受AddOne 类型的委托。

【讨论】:

  • 所以我已经做到了,而且效果很好。问题是它超级慢。在性能测试中,93% 的函数调用时间都花在了 System.Reflection.Emit.DynamicMethod.CreateDelegate(Type,Object) 中。由于我在一个紧密的循环中多次调用这个函数,我在想如果我可以自己调用一次它就不需要每次都调用它。
  • @heneryville 只要您只调用一次Compile,就不会花费那么长时间。我尝试在 for 循环中调用 Test(compiled),但在 100000000 次迭代时才明显减速(~0.466 秒)。
  • @heneryville 我在您的问题中看不到任何有关性能的信息。如果工作正常,有什么理由不接受
  • @heneryville 我认为你的真实代码有很大不同,你只是为了这个问题而把它弄糊涂了。也许您可以包含有关您实际在做什么的更多详细信息,并且有人可以提出性能更好的替代方案?另外,我们在谈论什么类型的性能(多少单位的 93%?)
  • @EkoostikMartin 嗯,是的。实际上,我还有一篇关于更大问题的帖子,但我对 CreateDelegate 非常感兴趣,所以我提出了这个问题来关注它。见stackoverflow.com/questions/19016898/…
猜你喜欢
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 2020-07-05
  • 1970-01-01
  • 2019-11-17
  • 2016-04-14
  • 2017-01-20
相关资源
最近更新 更多