【问题标题】:c# build generic Expression tree for list containsc#为列表包含构建通用表达式树
【发布时间】:2019-07-12 15:48:59
【问题描述】:

您好,我想创建一个通用表达式树,它返回一个包含结果的列表。

public static class Extension{
    public static List<T> WhereIn<T, T1>(IQueryable<T> query, IEnumerable<T1> keys, Expression<Func<T, T1>> param)
    {
    }
}

问题是我也想创建这样的东西:

var result = Extension.WhereIn(customers.AsQueryable(), stringList, c => c.Number.ToString());

到目前为止,这适用于静态属性名称:

public static Expression<Func<T, bool>> FilterByCode<T, T1>(List<T1> codes, string propName)
{
    var methodInfo = typeof(List<T1>).GetMethod("Contains", 
        new Type[] { typeof(T1) });

    var list = Expression.Constant(codes);

    var param = Expression.Parameter(typeof(T), "j");
    var value = Expression.Property(param, propName);
    var body = Expression.Call(list, methodInfo, value);

    // j => codes.Contains(j.Code)
    return Expression.Lambda<Func<T, bool>>(body, param);
}

【问题讨论】:

  • 我不明白你的问题。 WhereInA 应该怎么做?您能否对预期的表达式进行硬编码或添加一个示例来说明它应该如何工作?
  • 基本上 WhereIn(WhereInA 的 A 太多了)方法应该创建一个 contains 表达式。但是就像您在第二个代码 Extension.WhereIn... 中看到的那样,它应该获得一个可查询的、一个列表和一个表达式作为参数。对我来说棘手的部分是传递一个不是成员表达式的表达式,而是类似于:c => c.Number.ToString()

标签: c# lambda expression


【解决方案1】:

感谢Marc Gravell我得到了解决方案:

  public List<T> WhereIn<T, TValue>(IQueryable<T> source, IEnumerable<TValue> keys, Expression<Func<T, TValue>> selector)
  {
     MethodInfo method = null;
     foreach (MethodInfo tmp in typeof(Enumerable).GetMethods(
        BindingFlags.Public | BindingFlags.Static))
     {
        if (tmp.Name == "Contains" && tmp.IsGenericMethodDefinition
                                   && tmp.GetParameters().Length == 2)
        {
           method = tmp.MakeGenericMethod(typeof(TValue));
           break;
        }
     }
     if (method == null) throw new InvalidOperationException(
        "Unable to locate Contains");
     var row = Expression.Parameter(typeof(T), "row");
     var member = Expression.Invoke(selector, row);
     var values = Expression.Constant(keys, typeof(IEnumerable<TValue>));
     var predicate = Expression.Call(method, values, member);
     var lambda = Expression.Lambda<Func<T, bool>>(
        predicate, row);
     return source.Where(lambda).ToList();
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多