LINQ中类似对象的动态表达式

时间:2017-02-12 23:04:06

标签: c# linq lambda

我有一个名为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)));

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

1 个答案:

答案 0 :(得分:0)

感谢您的回答: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。