Lambda - C# - 动态表达式,使用string.IsNullOrEmpty

时间:2013-02-12 08:37:50

标签: c# dynamic lambda expression

我有以下代码块用于对通用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 =&gt;(item.Counterparty.ToLower()==“交易对手名称”)}

我在Lambda表达式中真正需要的是: -

{item =&gt; !string.IsNullEmptyOrWhitespace(item.Counterparty)&amp;&amp; (item.Counterparty.ToLower()==“交易对手名称”)}

如何动态实现这一点?

- 已审查 -

这是整个替换代码,使用更好的string.Equals检查

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

1 个答案:

答案 0 :(得分: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));
相关问题