从技术上讲,是的,你可以做到,但你需要构建Expression
自己传递给Where
.
也就是说,您应该考虑接受一个字符串值,而不是接受该属性Expression<Func<T, string>>
作为参数,以便您可以在编译时支持验证所选对象是否有效。
我们将从代表通用部分的表达式开始;它将表示一个带有*两个*参数、对象和给定属性的值的函数。然后,我们可以用我们在实际方法的参数中定义的属性选择器替换第二个参数的所有实例。
public static IQueryable<T> FilterByValue<T>(
this IQueryable<T> obj,
Expression<Func<T, string>> propertySelector,
string propertyValue)
{
if (!string.IsNullOrEmpty(propertyValue))
{
Expression<Func<T, string, bool>> expression =
(ex, value) => SqlFunctions.PatIndex(propertyValue.Trim(),
value.Trim()) > 0;
var newSelector = propertySelector.Body.Replace(
propertySelector.Parameters[0],
expression.Parameters[0]);
var body = expression.Body.Replace(expression.Parameters[1],
newSelector);
var lambda = Expression.Lambda<Func<T, bool>>(
body, expression.Parameters[0]);
return obj.Where(lambda);
}
else
return obj;
}
此方法使用一个函数将给定表达式中一个表达式的所有实例替换为另一个表达式的实例。其实现是:
public class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
If you really想要接受属性名称作为字符串然后只需替换定义newSelector
具有以下内容:
var newSelector = Expression.Property(expression.Parameters[0], propertyName);