Expression.Lambda和运行时生成查询,最简单的“Where”示例

53

我试图在运行时生成一个简单的Lambda表达式,但一直没有成功……大概像这样:

var result = queryableData.Where(item => item.Name == "Soap")

这是我的示例类和一个可查询的fixture:

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
}

IQueryable<Item> queryableData = ...;

然后我在运行时生成一个lambda表达式,正确的代码如下:

//"item" in "item =>..."
var item = Expression
    .Parameter(typeof(Item), "item");

//property of my item, this is "item.Name"
var prop = Expression
    .Property(item, "Name");

//then "Soap" in '... => item.Name=="Soap"'
var value = Expression.Constant("Soap");

//equality expression "==" in my primer
var equals = Expression.Equal(prop, value);

//then lambda
var lambda = Expression.Lambda<Func<Item, bool>>(equals, item);

//and here are the results    
var results = queryableData.Where(lambda);

非常感谢dtb的建议!


这是一个带有嵌套属性的扩展示例:https://dev59.com/llsX5IYBdhLWcg3wDsA8 - Piotr Czarnecki
1个回答

151

在以下查询中:

var result = query.Where(item => item.Name == "Soap")

lambda表达式是什么?

item => item.Name == "Soap"
你只需要构建这部分,而不是接受表达式树的 Where 调用。 lambda表达式的表达式树如下所示:
                     Lambda
                      /  \
                   Equal  Parameter
                   /   \    item
              Property  \
               "Name"   Constant
                 |       "Soap"
             Parameter         
               item

在代码中:

var item = Expression.Parameter(typeof(Item), "item");

var prop = Expression.Property(item, "Name");

var soap = Expression.Constant("Soap");

var equal = Expression.Equal(prop, soap);

var lambda = Expression.Lambda<Func<Item, bool>>(equal, item);

var result = queryableData.Where(lambda);

抱歉,但有些地方不够清晰。这是第二个表达式:var propId = Expression.Property(item, "Id"); var minId = Expression.Constant(15); var greaterThan = Expression.GreaterThan(propId, minId); 为了在lambda中结合等于大于,我需要 var combined = Expression.AndAlso(equal, greaterThan);,我是对的吗? - CodeAddicted
@dtb 我有一个对象列表,其中包含像{id = 1, year = "Year1", month = "Jan", val = 100, othval = 100}这样的对象,我需要的是{ id = 1 , Year1 = { Jan = { val = 100, othval = 100} }},其中我不知道year值,也不知道month。这可以在linq中实现吗? - Bharadwaj
我不明白为什么要使用params ParameterExpression[]?在这个代码中的"item"://然后是lambda表达式 var lambda = Expression.Lambda<Func<Item, bool>>(equals, item);你有一个多于一个参数的例子吗? - Raphael Ribeiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接