Arbre d'expression LINQ

c# expression-trees linq

Question

Je souhaite générer des arbres d'expression à l'aide de l'API pour les éléments suivants:

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

De plus, comment puis-je générer l’arbre d’expression pour faire ceci:

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

Je suis arrivé avec ce qui suit jusqu'ici pour le .Where (), mais il d'erreur, car il n'aime pas les paramètres de type dans 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);

Réponse acceptée

J'ai eu ça. Les paramètres de type sur Any et Where doivent être Employee , et non IQueryable<Employee> ou IEnumerable<Employee> car ils ne recherchent que les paramètres de type, pas les types réels. Je crois que vous avez également besoin d'un Expression.Constant(dataContext.Employees) au lieu d'un simple 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);

Réponse populaire

Pour appeler Any pour votre MemberExpression vous devriez le faire

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);

et Where

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


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow