5

我正在为通用过滤器使用下面的代码,任何通过的搜索文本但包含方法是区分大小写的,我该如何编写来忽略大小写。

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);       
    }

}
4

4 回答 4

12

不要调用 String.Contains,而是使用不区分大小写的StringComparison参数调用String.IndexOf 。然后将其结果与 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您可以避免为同一个作业创建两个重载。

于 2013-07-25T10:45:51.320 回答
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)));
于 2013-07-25T10:26:50.843 回答
0

如果要过滤或搜索列表中的值,请参考以下代码。此外,它是一种通用方法,可帮助您从列表中过滤任何类型的类或对象。它在 SQL 中用作类似子句,例如 (column1 like '%abc%' or column2 like '%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();
于 2020-11-26T17:37:58.617 回答
-1

首先将两个参数转换为大写可能是最简单的(在 .NET 中,大写转换比小写转换优化得更好)。然后,您可以进行比较。

大写转换可以这样完成:

var expression = Expression.Call(property, typeof(string).GetMethod("ToUpperInvariant", System.Type.EmptyTypes));
于 2013-07-25T10:34:35.170 回答