5

以下のコードを 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

4 に答える 4

12

String.Contains を呼び出す代わりに、大文字と小文字を区別しないStringComparisonパラメータを指定してString.IndexOfを呼び出します。次に、 Expression.GreaterThanOrEqual式を使用して、その結果を 0 と比較します。Expression.Call に追加のパラメーターを Expression.Constant として提供する必要があります。

大文字と小文字を区別しない StringComparison オプションの 1 つをハードコーディングするか、それを 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で、同じジョブに対して 2 つのオーバーロードを作成することを回避できます。

于 2013-07-25T10:45:51.320 に答える
-1

最初に両方のパラメーターを大文字に変換するのがおそらく最も簡単です (.NET では、大文字の変換は小文字の変換よりも最適化されます)。その後、比較を行うことができます。

大文字変換は次のように行うことができます。

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