【问题标题】:Create Expression<Func<T, TKey>> dynamically动态创建 Expression<Func<T, TKey>>
【发布时间】:2017-09-19 05:03:53
【问题描述】:

相关:Create a Lambda Expression With 3 conditions

请考虑这个GroupBy 声明:

group r by new { r.EmployeeID, r.Name }

如果我想用Lambda 版本在上面写GroupBy 语句并将Expression&lt;Func&lt;T, TKey&gt;&gt; 作为参数传递给它,我该如何创建Expression&lt;Func&lt;T, TKey&gt;&gt;

【问题讨论】:

  • @shA.t:不,“动态”我很确定他的意思是他不想让代码在编译时指定 EmployeeID 和 Name。他想改用在运行时已知的信息。
  • 谢谢,但我想创建Expression&lt;Func&lt;T, TKey&gt;&gt; using Expressions`。请参阅参考的链接
  • @StriplingWarrior 是的,你是对的
  • 你在构建这个表达式的时候有什么信息?你知道哪些值构成组键吗?你知道他们的类型吗?您能否包含一些显示示例用例的代码?

标签: c# entity-framework linq c#-4.0 lambda


【解决方案1】:

我没有时间带您完成整个过程,但一般要点是您将使用 Expression 类的静态方法构造表达式。

例如,new 表达式将通过将构造函数信息和一系列表达式等传递给Expression.New() 重载之一来创建。

r =&gt; ... 的概念体现在 Expression.Lambda&lt;Func&lt;T, TKey&gt;&gt;(...) 中,您将 Expression.Parameter(typeof(T), "r") 作为 lambda 的参数传递。

Expression.MakeMemberAccess 将帮助您生成r.EmployeeIdr.Name

我发现首先在 LINQPad 中转储一个示例表达式很有用,代码如下:

void Main()
{
    DumpExp(r => new { r.EmployeeID, r.Name });
}

public void DumpExp<TKey>(Expression<Func<Foo, TKey>> expr)
{
    expr.Dump();
}

public class Foo
{
    public string EmployeeID;
    public string Name;
}

这将允许您检查树并了解构成树的表达式类型以及它们的属性值是什么。然后你可以尝试编写代码来匹配。

一旦你有了一个你认为可以工作的表达式,你可以在它上面调用 Compile 来产生一个可运行的函数,你可以用它来测试它在内存对象上的行为。

我猜你的匿名类型可能是问题中最困难的部分。如果目标框架在其 GroupBy 语句中支持元组之类的东西,那么您最好使用它们来代替。

有一个旧项目旨在使您能够运行通过向类似 LINQ 的方法提供字符串而构建的动态 LINQ 语句。它被称为“动态 LINQ”,它可能适合您的需求。

您可能还会发现this library 很有用。它应该可以帮助您使用更流畅的语法构建表达式树。但是,它似乎没有在积极开发中。

【讨论】:

  • 很好的答案...有一些关于这个主题的文档,如果可能的话,我想请你在这里写下上述声明。我没有以这种方式使用表达式,如果我能看到一个工作示例,正确搜索将非常有帮助
  • @Arian:我没有时间为你写这篇文章,但你可以看到 this post 一个很好的一般例子,你应该能够适应你的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多