【问题标题】:Dynamic Expression in LINQ for Similar ObjectsLINQ 中类似对象的动态表达式
【发布时间】:2017-02-12 23:04:06
【问题描述】:

我有一个名为 FindAll() 的服务方法,它需要一个表达式/谓词参数并返回所有匹配的行。

假设我有一个 Book 对象的集合,我想在字符串列表中获取所有书籍及其名称。我会有这样的东西:

var lstNames = { "Book1", "Book2" };
var matchedBooks = myService<Book>.FindAll(x => lstNames.Any(y => x.Name.Equals(y)));

我还有许多其他类都具有 Name 属性,所以我想构建一个动态表达式,它允许我执行以下操作:

var matchedObjs = myService<T>.FindAll(x => lstNames.Any(y => x.Name.Equals(y)));

如何构建这样的动态表达式?

【问题讨论】:

  • 要么使用接口,要么使用动态变量
  • 也不想这样做。 EF 生成这些类,即使可以,也不想在其上添加接口。创建动态表达式似乎是最简洁的方法。
  • 您使用FindAll而不是Where的任何原因?
  • 另外,您是否有理由要避免使用上述相当简单的语法?你可以稍微简化一下:x =&gt; lstNames.Contains(x.Name)
  • @DavidG,这绝对是真的。如果我只使用包含,我可以更简化这一点。谢谢。

标签: c# linq lambda


【解决方案1】:

感谢这个答案:How to declare a Linq Expression variable in order to have it processed as a dbParameter

我建议你这样做:

static Expression<Func<T, bool>> GetExpr<T> (string name, string value)
{
  ParameterExpression param = Expression.Parameter(typeof(T), "x");
  Expression prop = Expression.Property(param, name); // this is the property name, e.g. .Name
  Expression<Func<string>> valueLambda = () => value; // This is the value for == expression.
  Expression lookupExpression = Expression.Equal(prop, valueLambda.Body);

  Expression<Func<T, bool>> expr = Expression.Lambda<Func<T, bool>>(lookupExpression, param);

  return expr;
}

... 或者,对于 .Contains():

static Expression<Func<T, bool>> GetExprContains<T>(string name, string[] value)
{
  ParameterExpression param = Expression.Parameter(typeof(T), "x");
  Expression prop = Expression.Property(param, name); // this is the property name, e.g. .Name
  Expression<Func<string[]>> valueLambda = () => value; // This is the value for .Contains() expression.
  var mi =
    typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
      .FirstOrDefault(x => x.Name == "Contains" && x.GetParameters().Count() == 2)
      .MakeGenericMethod(typeof(string)); // Need methodinfo for .Contains(), might want to keep static somewhere
  var lookupExpr = Expression.Call(null, mi, valueLambda.Body, prop);

  Expression<Func<T, bool>> expr = Expression.Lambda<Func<T, bool>>(lookupExpr, param);

  return expr;
}

经过测试,可与 EF 配合使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多