【问题标题】:LINQ Expression Tree [duplicate]LINQ 表达式树 [重复]
【发布时间】:2013-05-30 06:37:34
【问题描述】:

我想使用以下 API 生成表达式树:

var managers = dataContext.Employees.Where(e => e.Subordinates.Any());

此外,我如何生成表达式树来执行此操作:

var managedEmployees = managers.ToDictionary(key => key.Manager, value => value.Subordinates.Select(s => s.FullName));

到目前为止,我已经为 .Where() 提出了以下内容,但它出错了,因为它不喜欢 new Type[] { typeof(Func<Employee, IEnumerable<Employee>>) } 中的类型参数。

ParameterExpression employeesParameter = Expression.Parameter(typeof(Employee), "e");
MemberExpression subordinatesProperty = Expression.Property(employeesParameter, typeof(Employee).GetProperty("Subordinates"));
MethodCallExpression hasSubordinates = Expression.Call(typeof(Enumerable),
  "Any",
  new Type[] { typeof(Employee) },
  subordinatesProperty);
LambdaExpression whereLambda = Expression.Lambda(hasSubordinates, employeesParameter);
MethodCallExpression whereExpression = Expression.Call(typeof(Queryable),
  "Where",
  new Type[] { typeof(Func<Employee, IEnumerable<Employee>>) },
  dataContext.Employees.AsQueryable(),
  whereLambda);

【问题讨论】:

  • 对于初学者“where”应该通过methodinfo调用来调用。括号内的东西是表达式
  • 不,如果我从 Where() 中删除 Any() 并将其设置为其他内容,例如说 Where(e => e.EmployedDate > '1/1/2013',这对我有用)。然后我可以将类型从 Func> 更改为 Employee,它可以按预期工作。问题完全在于 Any() 函数,我不知道要提供什么类型。
  • 请不要多次发布同一个问题。如果您有什么要补充的,请编辑您的原始问题。
  • 公平地说,另一个问题没有得到答案。
  • 另一个问题似乎完全让所有看过它的人感到困惑。所以我用更通用的代码尝试了这个问题。

标签: c# linq expression-trees


【解决方案1】:

我明白了。 AnyWhere 上的类型参数需要是 Employee,而不是 IQueryable&lt;Employee&gt;IEnumerable&lt;Employee&gt;,因为它只是在寻找类型参数,而不是实际类型。我相信您还需要Expression.Constant(dataContext.Employees) 而不是直接的dataContext.Employees

ParameterExpression employeesParameter = Expression.Parameter(typeof(Employee), "e");
MemberExpression subordinatesProperty = Expression.Property(employeesParameter, typeof(Employee).GetProperty("Subordinates"));

MethodCallExpression hasSubordinates = Expression.Call(typeof(Enumerable),
    "Any",
    new Type[] { typeof(Employee) },
    subordinatesProperty);
LambdaExpression whereLambda = Expression.Lambda(hasSubordinates, employeesParameter);
MethodCallExpression whereExpression = Expression.Call(typeof(Queryable),
    "Where",
    new Type[] { typeof(Employee) },
    Expression.Constant(dataContext.Employees),
    whereLambda);

【讨论】:

  • 还是不行。我仍然收到错误消息:“类型 'System.Linq.Enumerable' 上的通用方法 'Where' 与提供的类型参数和参数兼容。如果方法是非通用的,则不应提供类型参数。”反对 whereExpression 声明。
  • 我没有收到那个错误。我用上面的代码逐字复制/粘贴。
【解决方案2】:

要为您的MemberExpression 调用Any,您应该这样做

ParameterExpression employeesParameter = Expression.Parameter(typeof(Employee), "e");
MemberExpression subordinatesProperty = Expression.Property(employeesParameter, typeof(Employee).GetProperty("Subordinates"));

var mi = typeof(Enumerable).GetMethods().First(x => x.Name == "Any" && x.GetParameters().Length == 1);
mi = mi.MakeGenericMethod(typeof (bool));
var hasSubordinates = Expression.Call(mi, subordinatesProperty);

Where

var lambda = Expression.Lambda<Func<Employee, bool>>(hasSubordinates, employeesParameter);
var res = i.Where(lambda.Compile());

【讨论】:

  • 这不会编译。你在 var res = i.Where(lambda.Compile());??中声明了“i”??
  • i 是任何可枚举的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
  • 1970-01-01
  • 2016-04-17
  • 1970-01-01
  • 2012-02-17
相关资源
最近更新 更多