Ответ 1
Технически, да, вы могли бы это сделать, но вам нужно было бы построить Expression
самостоятельно, чтобы перейти к Where
.
При этом вместо того, чтобы принимать свойство как строковое значение, вы должны вместо этого принять Expression<Func<T, string>>
как параметр, чтобы у вас была поддержка времени компиляции для проверки того, что выбранный объект действителен.
Мы начнем с выражения, которое представляет общую часть; он будет представлять функцию с параметрами * two *, объектом и значением данного свойства. Затем мы можем заменить все экземпляры этого второго параметра на селектор свойств, который мы определили в фактических параметрах метода.
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);
}
Если вы действительно хотите принять имя свойства как строку, просто замените определение newSelector
на следующее:
var newSelector = Expression.Property(expression.Parameters[0], propertyName);