创建表达式<func <t,tkey =“”>&gt;动态

时间:2017-09-19 05:03:54

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

相关:Create a Lambda Expression With 3 conditions

请考虑此GroupBy声明:

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

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

1 个答案:

答案 0 :(得分:2)

我没有时间引导你完成整个事情,但一般的要点是你将使用Expression类之外的静态方法构造表达式。

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

r => ...的概念由Expression.Lambda<Func<T, TKey>>(...)体现,您传递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语句中支持像Tuples这样的东西,那么最好使用它们。

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

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