使用通用LINQ表达式为包含方法调用忽略大小写

时间:2013-07-25 10:04:31

标签: c# .net linq linqkit

我使用下面的代码来处理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);       
    }

}

4 个答案:

答案 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));