Kel*_*ine 3 c# expression-trees
我想在Where-Contains 和Select 中都有一个变量字段。“field_a”是我想要变量的人(有时我想要 field_b 或 _c;它们是字符串)。下面的代码正确构建了 Select as Select(x => x.field_a)。如何让Where子句的第二部分说,&& targetCodes.Contains(x.field_a)?[db是一个DbContext,itemsArray是具有名为 的字符串属性的对象数组Code。]
using (var db = dbFactory.CreateInstance())
{
var parameter = Expression.Parameter(typeof(myTable), "x");
var field = Expression.Property(parameter, "field_a");
var selector = Expression.Lambda(field, parameter);
var targetCodes = itemsArray.Select(i => i.Code).ToArray();
var query = db.myTables
.Where(x => x.companyId == 1 && targetCodes.Contains(x.field_a))
.Select((Expression<Func<myTable, string>>)selector);
return await query.ToArrayAsync();
}
Run Code Online (Sandbox Code Playgroud)
也许最困难的部分是找到MethodInfo方法.Contains()。您可以使用typeof(IEnumerable<string>).GetMethod(...).Where(...),但对于具有多个重载的泛型方法来说通常很难做到正确。这是一个小技巧,它使用 C# 编译器通过创建临时表达式来找到正确的重载:
Expression<Func<IEnumerable<string>, bool>> containsExpr = (IEnumerable<string> q) => q.Contains((string)null);
var containsMethod = (containsExpr.Body as MethodCallExpression).Method;
// containsMethod should resolve to this overload:
// System.Linq.Enumerable.Contains<string>(IEnumerable<string>, string)
Run Code Online (Sandbox Code Playgroud)
程序的其余部分只是通过调用适当的Expression.XYZ()方法来构建表达式:
var companyIdEquals1 = Expression.Equal(
Expression.Property(parameter, nameof(myTable.companyId)),
Expression.Constant(1));
var targetCodesContains = Expression.Call(
containsMethod,
Expression.Constant(targetCodes),
field/*reuses expression you already have*/);
var andExpr = Expression.And(companyIdEquals1, targetCodesContains);
var whereExpr = (Expression<Func<myTable, bool>>)Expression.Lambda(andExpr, parameter);
var query = db//.myTables
.Where(whereExpr)
.Select((Expression<Func<myTable, string>>)selector);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1277 次 |
| 最近记录: |