在数据表对象上调用表达式
calling expression on datatable object
我正在尝试使用表达式树动态构建对我的数据的查询table,目前用于测试的数据由单个 table:
组成
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))}
不,我有问题 - 如何在我的数据上调用该表达式table?或者我应该将 datatable 转换为 enumarable?
首先,不需要第二个 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()
等等。 .
首先,正如另一个答案中已经提到的,您不需要第二个参数。但更重要的是,您的代码生成的内容未绑定到特定的 "column" 或 "property" - 生成的编译 lambda 类似于这样
Func<int, bool> predicate = (int Id) => (Id == 14 && Id != 15);
也就是说,这是一个接收int
参数和returnsbool
的函数。 Id
只是参数的名称,您可以传递任何 int
值。因此,它不能直接用作期望 Func<User, bool>
的 IEnumerable<User>
上的 Where
条件,也不能直接用作期望 Func<DataRow, bool>
的 IEnumerable<DataRow>
上的条件。
为了使其可用于 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();
现在你可以这样使用了
List<User> users = ...;
var filteredUsers = users.Where(userFilter).ToList();
我正在尝试使用表达式树动态构建对我的数据的查询table,目前用于测试的数据由单个 table:
组成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))}
不,我有问题 - 如何在我的数据上调用该表达式table?或者我应该将 datatable 转换为 enumarable?
首先,不需要第二个 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()
等等。 .
首先,正如另一个答案中已经提到的,您不需要第二个参数。但更重要的是,您的代码生成的内容未绑定到特定的 "column" 或 "property" - 生成的编译 lambda 类似于这样
Func<int, bool> predicate = (int Id) => (Id == 14 && Id != 15);
也就是说,这是一个接收int
参数和returnsbool
的函数。 Id
只是参数的名称,您可以传递任何 int
值。因此,它不能直接用作期望 Func<User, bool>
的 IEnumerable<User>
上的 Where
条件,也不能直接用作期望 Func<DataRow, bool>
的 IEnumerable<DataRow>
上的条件。
为了使其可用于 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();
现在你可以这样使用了
List<User> users = ...;
var filteredUsers = users.Where(userFilter).ToList();