在datatable对象上调用表达式

时间:2016-01-10 10:18:03

标签: c# .net datatable expression

我想使用表达式树动态地构建对我的数据表的查询,当前测试由单数表组成:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public Boolean IsSuperUser { get; set; }
    public DateTime RegisterDate { get; set; }
    public DateTime LastLoginDate { get; set; }
    public Int32 RandomIntValue { get; set; }
}

所以我编写了一个为我创建测试表达式的代码:

 var column = generatedDatatable.Columns[0];

 ParameterExpression pe = Expression.Parameter(column.DataType, column.ColumnName);
 ConstantExpression value = Expression.Constant(14);
 Expression eq = Expression.Equal(pe, value);

 ParameterExpression pe2 = Expression.Parameter(column.DataType, column.ColumnName);
 ConstantExpression value2 = Expression.Constant(15);
 Expression eq2 = Expression.NotEqual(pe2, value2);

 Expression final = Expression.And(eq, eq2);

我的最终变量包括:

  
    

{((Id == 14)And(Id!= 15))}

  

不,我有问题 - 如何在我的数据表上调用该表达式?或者我可能应该将数据转换为可用的?

2 个答案:

答案 0 :(得分:2)

首先,不需要第二个ParameterExpression实例,并且您的参数必须是User类型的成员:

var parameter = Expression.Parameter(typeof(User), "source");
var memberOwnerParameter = Expression.PropertyOrField(source, propertyName); // propertyName is "Id" in your case.

ConstantExpression value = Expression.Constant(14);
Expression eq = Expression.Equal(memberOwnerParameter, value);

ConstantExpression value2 = Expression.Constant(15);
Expression eq2 = Expression.NotEqual(memberOwnerParameter, value2);

Expression final = Expression.And(eq, eq2);

然后,如果你的来源是IQueryable,那么:

var resultExpression = Expression.Lambda<Func<User, bool>>(final, memberOwnerParameter);
var result = source.Where(resultExpression);

否则,如果你的来源是IEnumerable,那么:

var resultExpression = Expression.Lambda<Func<User, bool>>(final, memberOwnerParameter);
var resultDelegate = resultExpression.Compile();
var result = source.Where(resultDelegate);

然后,您可以调用所需的Linq方法,例如ToList()ToArray()First()Single()Select()等等...... < / p>

答案 1 :(得分:2)

首先,正如另一个答案中已经提到的,您不需要第二个参数。但更重要的是,您的代码生成的内容并未绑定到特定的“列”或“属性” - 生成的编译lambda就是这样的

Func<int, bool> predicate = (int Id) => (Id == 14 && Id != 15);

换句话说,这是一个接收int 参数并返回bool的函数。 Id只是参数的名称,您可以传递任何int值。因此,它不能直接用作期望Where的{​​{1}}上的IEnumerable<User>条件,也不能用于期望Func<User, bool>的{​​{1}}上的IEnumerable<DataRow>条件。

为了使其可用于Func<DataRow, bool>,表达式必须构建在IEnumerable<User>类型的单个参数之上,如此

User

现在你可以像这样使用它了

string memberName = ...;
var source = Expression.Parameter(typeof(User), "source");
var member = Expression.PropertyOrField(source, memberName); 
var cond1 = Expression.Equal(member, Expression.Constant(14));
var cond2 = Expression.NotEqual(member, Expression.Constant(15));
var cond = Expression.And(cond1, cond2);
var lambda = Expression.Lambda<Func<User, bool>>(cond, source);
var userFilter = lambda.Compile();