我使用下面的代码来处理Generic Filter,传递了任何搜索文本,但contains方法是区分大小写的,如何编写忽略大小写。
public static class QueryExtensions
{
public static IQueryable<T> Filter<T>(this IQueryable<T> query, string search)
{
var properties = typeof(T).GetProperties().Where(p =>
/*p.GetCustomAttributes(typeof(System.Data.Objects.DataClasses.EdmScalarPropertyAttribute),true).Any() && */
p.PropertyType == typeof(String));
var predicate = PredicateBuilder.False<T>();
foreach (var property in properties )
{
predicate = predicate.Or(CreateLike<T>(property,search));
}
return query.AsExpandable().Where(predicate);
}
private static Expression<Func<T,bool>> CreateLike<T>( PropertyInfo prop, string value)
{
var parameter = Expression.Parameter(typeof(T), "f");
var propertyAccess = Expression.MakeMemberAccess(parameter, prop);
var like = Expression.Call(propertyAccess, "Contains", null, Expression.Constant(value,typeof(string)));
return Expression.Lambda<Func<T, bool>>(like, parameter);
}
}
答案 0 :(得分:7)
不是调用String.Contains,而是使用不区分大小写的String.IndexOf参数调用StringComparison。然后将其结果与0进行比较,并使用Expression.GreaterThanOrEqual表达式。您需要在Expression.Call中提供额外参数作为Expression.Constant。
您可以决定对其中一个不区分大小写的StringComparison选项进行硬编码,或将其作为Filter方法的参数导出,从而允许用户决定是否需要不区分大小写的搜索。
您可以这样做:
private static Expression<Func<T, bool>> CreateLike<T>(PropertyInfo prop, string value)
{
var parameter = Expression.Parameter(typeof(T), "f");
var propertyAccess = Expression.MakeMemberAccess(parameter, prop);
var indexOf = Expression.Call(propertyAccess, "IndexOf", null, Expression.Constant(value, typeof(string)),Expression.Constant(StringComparison.InvariantCultureIgnoreCase));
var like=Expression.GreaterThanOrEqual(indexOf, Expression.Constant(0));
return Expression.Lambda<Func<T, bool>>(like, parameter);
}
或使用StringComparison参数
private static Expression<Func<T, bool>> CreateLike<T>(PropertyInfo prop,
string value,
StringComparison comparison=StringComparison.InvariantCultureIgnoreCase)
{
var parameter = Expression.Parameter(typeof(T), "f");
var propertyAccess = Expression.MakeMemberAccess(parameter, prop);
var indexOf = Expression.Call(propertyAccess, "IndexOf", null,
Expression.Constant(value, typeof(string)),
Expression.Constant(comparison));
var like=Expression.GreaterThanOrEqual(indexOf, Expression.Constant(0));
return Expression.Lambda<Func<T, bool>>(like, parameter);
}
通过使用comparison
的默认值,您可以避免为同一作业创建两个重载。
答案 1 :(得分:1)
您可以尝试使用String.IndexOf
。
string x,y = string.Empty;
x.IndexOf(y,0,x.Length, StringComparison.CurrentCultureIgnoreCase) > -1
因为它有一个StringComparison参数。
这将返回一个整数
var like = Expression.Call(propertyAccess, "IndexOf", null, Expression.Constant(value, typeof(string)), Expression.Constant(StringComparison.CurrentCultureIgnoreCase,typeof(StringComparison)));
答案 2 :(得分:0)
如果要过滤或从列表中搜索值,请参考以下代码。此外,它是一种通用方法,可帮助您从列表中过滤任何类型的类或对象。它在SQL中像like子句一样工作,例如(column1如'%abc%'或column2如'%abc%')。
public static class Filter<T>
{
public static Expression<Func<T, bool>> FilterExpression(string searchValue)
{
Expression finalExpression = Expression.Constant(false);
var parameter = Expression.Parameter(typeof(T), "x");
PropertyInfo[] propertyInfos = typeof(T).GetProperties();
foreach (PropertyInfo propertyInfo in propertyInfos)
{
if (propertyInfo.PropertyType == typeof(string))
{
var propertyExpn = Expression.Property(parameter, propertyInfo.Name.Trim().ToLower());
var containsExpn = Expression.Call(propertyExpn, "Contains", null, Expression.Constant(searchValue, typeof(string)), Expression.Constant(StringComparison.InvariantCultureIgnoreCase));
var nullCheckExpn = Expression.NotEqual(propertyExpn, Expression.Constant(null, typeof(string)));
var andAlsoExpn = Expression.AndAlso(nullCheckExpn, containsExpn);
finalExpression = Expression.Or(finalExpression, andAlsoExpn);
}
}
var rowFilterLambdaExpression = Expression.Lambda<Func<T, bool>>(finalExpression, new ParameterExpression[] { parameter });
return rowFilterLambdaExpression;
}
}
用法,例如
var result =
dataItems.Where(Filter<T>.FilterExpression(model.FilterValue).Compile()).ToList();
答案 3 :(得分:-1)
将两个参数首先转换为大写可能是最简单的(大写转换优于.NET中的小写转换)。然后,您可以进行比较。
大写转换可以像这样完成:
var expression = Expression.Call(property, typeof(string).GetMethod("ToUpperInvariant", System.Type.EmptyTypes));