3

我有以下代码块用于对通用 IQueryable 列表执行一些动态过滤

    private static MethodInfo miTL = typeof(String).GetMethod("ToLower", Type.EmptyTypes);

    public static IQueryable<T> Where<T>(IQueryable<T> source, string member, object value)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
        if (member == null)
        {
            throw new ArgumentNullException("member");
        }
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        if (value is string && !string.IsNullOrWhiteSpace(value.ToString()))
        {
            //If the type is string, force lowercase equals comparison for both sides.
            value = value.ToString().ToLower();

            var parameter = Expression.Parameter(typeof(T), "item");
            var parameterProperty = Expression.Property(parameter, member);

            //ToLower dynamic expression
            var dynamicExpression = Expression.Call(parameterProperty, miTL);

            var constantValue = Expression.Constant(value);
            var equalsExpression = Expression.Equal(dynamicExpression, constantValue);

            var lambdaExpression = Expression.Lambda<Func<T, bool>>(equalsExpression, parameter);

            return source.Where(lambdaExpression);
        }
        else
        {
            var item = Expression.Parameter(typeof(T), "item");
            var prop = Expression.Property(item, member);
            var soap = Expression.Constant(value);
            var equal = Expression.Equal(prop, soap);
            var lambda = Expression.Lambda<Func<T, bool>>(equal, item);
            return source.Where(lambda);
        }
    }

这一切都很好 - 除了我的源可能包含空值,然后返回空引用异常。

它直接转换为(当字段为“交易对手”时:- {item => (item.Counterparty.ToLower() == "交易对手名称")}

我实际需要的 Lambda 表达式形式是:-

{item => !string.IsNullEmptyOrWhitespace(item.Counterparty) && (item.Counterparty.ToLower() == "交易对手名称")}

任何想法如何动态实现这一目标?

--已审核--

这是整个替换代码,使用了更好的字符串。等于检查

    public static IQueryable<T> Where<T>(IQueryable<T> source, string member, object value)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
        if (member == null)
        {
            throw new ArgumentNullException("member");
        }
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        if (value is string && !string.IsNullOrWhiteSpace(value.ToString()))
        {
            var parameter = Expression.Parameter(typeof(T), "item");
            var parameterProperty = Expression.Property(parameter, member);

            var body =
                Expression.AndAlso(
                    Expression.Not(
                        Expression.Call(typeof(string), "IsNullOrEmpty", null, parameterProperty)
                    ),
                    Expression.Call(typeof(string), "Equals", null,
                        parameterProperty, Expression.Constant(value),
                        Expression.Constant(System.StringComparison.InvariantCultureIgnoreCase))
                );

            var body2 = Expression.Call(typeof(string), "Equals", null,
                parameterProperty, Expression.Constant(value),
                Expression.Constant(System.StringComparison.InvariantCultureIgnoreCase));

            var lambdaExpression = Expression.Lambda<Func<T, bool>>(body, parameter);

            return source.Where(lambdaExpression);
        }
        else
        {
            var item = Expression.Parameter(typeof(T), "item");
            var prop = Expression.Property(item, member);
            var soap = Expression.Constant(value);
            var equal = Expression.Equal(prop, soap);
            var lambda = Expression.Lambda<Func<T, bool>>(equal, item);
            return source.Where(lambda);
        }
    }
4

1 回答 1

3

直译是这样的:

var body =
    Expression.AndAlso(
        Expression.Not(
            Expression.Call(typeof(string), "IsNullOrWhiteSpace", null,
                                                       parameterProperty)
        ),
        Expression.Equal(
            Expression.Call(parameterProperty, "ToLower", null),
            Expression.Constant("name of counterparty")
        )
    );

但是,您最好查看各种string.Equals重载。例如:

var body = Expression.Call(typeof(string), "Equals", null,
    parameterProperty, Expression.Constant("name of counterparty"),
    Expression.Constant(System.StringComparison.InvariantCultureIgnoreCase));
于 2013-02-12T08:44:42.307 回答