Если все «бла» (классы), которые вы будете фильтровать, имеют одинаковую структуру, вы можете использовать простой метод, подобный этому.Основное отличие состоит в том, что он возвращает выражение, которое Linq должен уметь анализировать, и вводит весь экземпляр и фильтрует по имени, а не только по имени строки.
public static Expression<Func<T, bool>> BuildStringMatch<T>(string searchFor) where T : IHasName
{
return b =>
string.IsNullOrEmpty(searchFor) ||
(b.Name != null &&
(b.Name.Trim().ToLower().StartsWith(searchFor.Trim().ToLower()) ||
b.Name.Contains(" " + searchFor)));
}
Вы можете использовать этот методкак это:
IQueryable<Blah> blahs = query.Where(BuildStringMatch<Blah>(searchText));
Это предполагает, что все ваши классы, которые вы хотите фильтровать, реализуют некоторый интерфейс, такой как:
public interface IHasName
{
string Name { get; }
}
Если вы хотите фильтровать по разным свойствам,Я не думаю, что это то, что вы можете сделать с таким простым кодом.Я полагаю, что вам нужно создать Expression самостоятельно с помощью отражения (или с помощью библиотеки, которая использует отражение) - это все еще возможно, но гораздо сложнее.
Редактировать: Похоже, вам нужно динамическое поведение,поэтому я позаимствовал некоторую логику из ответа dtb на этот вопрос и придумал следующее:
public static Expression<Func<T, bool>> BuildStringMatch<T>(Expression<Func<T, string>> property, string searchFor)
{
var searchForExpression = Expression.Constant(searchFor, typeof(string));
return
Expression.Lambda<Func<T, bool>>(
Expression.OrElse(
Expression.Call(typeof(string), "IsNullOrEmpty", null, searchForExpression),
Expression.AndAlso(
Expression.NotEqual(property.Body, Expression.Constant(null, typeof(string))),
Expression.OrElse(
Expression.Call(Expression.Call(Expression.Call(property.Body, "Trim", null), "ToLower", null), "StartsWith", null,
Expression.Call(Expression.Call(searchForExpression, "Trim", null), "ToLower", null)),
Expression.Call(property.Body, "Contains", null, Expression.Call(typeof(string), "Concat", null, Expression.Constant(" "), searchForExpression))
)
)
),
property.Parameters
);
}
Вы бы использовали его следующим образом:
IQueryable<Blah> blahs2 = query.Where(BuildStringMatch<Blah>(b => b.Name, searchText));
Он длинный и многословный, но вы можете видеть, как он похож на оригинальный метод, написанный на простом коде C #.Примечание. Я не тестировал этот код, поэтому может возникнуть несколько небольших проблем, но это общая идея.