【问题标题】:C# Null check in expression treesC# Null 检查表达式树
【发布时间】:2017-09-04 09:51:35
【问题描述】:

我有一个名为 User 的类,其中有一个字段,用户可以在其中发送任何数据类型。目前我们正在发送 int、double 和 string。

由于字段是动态的,这意味着字段名称可以是我们使用表达式树的任何内容。我现在面临的问题是,如果选择查询中的字段为空或字段值为空,那么它会引发错误。

下面是我的代码:

Expression<Func<User, bool>> comparison = null;

if (Value.GetType() == typeof(int))
    comparison = EvaluateRules<int>(attributeName);
else if (Value.GetType() == typeof(double))
    comparison = EvaluateRules<double>(attributeName);
else if (Value.GetType() == typeof(string))
    comparison = EvaluateRules<string>(attributeName);


private Expression<Func<User, bool>> EvaluateRules<T>(string attributeName)
{
    var attributeParameter = Expression.Parameter(typeof(User), "user");
    Expression<Func<User, bool>> comparison = null;
    var parseMethod = typeof(T).GetMethod("Parse", new[] { typeof(string) });

    switch (policyOperator)
    {
        case Operator.GreaterThanOrEqual:
            if (Value.GetType() != typeof(string))
                comparison = Expression.Lambda<Func<User, bool>>(
                                    Expression.GreaterThanOrEqual(
                                        Expression.Call(parseMethod, Expression.Property(attributeParameter, attributeName)),
                                        Expression.Constant(Value)),
                                        attributeParameter);
            break;
    }

    return comparison;
}

resultUsers = from user in users.AsQueryable().Where(comparison) select user

有什么线索吗??

感谢您的宝贵时间。

【问题讨论】:

  • The issue I am facing now is if the field is null in the select query or the field value then it throws error. 它会抛出什么异常?在哪一行?
  • 它说“值不能为空。参数名称:字符串”。在下面的语句 resultUsers = from user in users.AsQueryable().Where(comparison) select user 中抛出此错误
  • 为什么不单独处理空值,而不是在其上调用 Parse 方法?例如。 Expression.OrElse(Expression.Equal(Expression.Property(attributeParameter, attributeName), Expression.Constant(null, typeof(T))), ...graterthan...) 顺便说一句,它会去数据库吗?如果不是,为什么要使用表达式树,而不是普通的 Funcs?
  • @MBoros .... 感谢您的回复。需要解析方法,因为列值将包含数字,而列类型本身是字符串。我们正在使用 mongo 数据库。当然,我们从 mongo db 获取用户列表。之所以使用表达式树,是因为我们事先并不知道列名。此列将在运行时动态绑定。

标签: c# expression-trees


【解决方案1】:

感谢您的回复。我能够用下面的代码解决它。发布它以防它帮助某人。

ParameterExpression attributeParameter = Expression.Parameter(typeof(User), "user");
MemberExpression attribute = Expression.Property(attributeParameter, attributeName);
BinaryExpression nullCheck = Expression.NotEqual(attribute, Expression.Constant(null, typeof(object)));
BinaryExpression condition = null;

 switch (policyOperator)
{
    case Operator.GreaterThanOrEqual:
    if (Value.GetType() != typeof(string))
        condition = Expression.GreaterThanOrEqual(Expression.Call(parseMethod, 
                        Expression.Property(attributeParameter, attributeName)), 
                            Expression.Constant(Value));

    .
    .
}

return Expression.Lambda<Func<User, bool>>(Expression.AndAlso(nullCheck, condition), attributeParameter);                           

【讨论】:

  • 顺便说一句,如果你想保持代码的可维护性,忘记低级 Expr API,并将编译器生成的表达式与(我自己做广告:P):*.com/questions/29448432/…
  • @MBoros .... 我上面的代码完全是一个单独的方法,它返回 lambda 表达式。此方法支持GreaterThanOrEqual等5种操作。如果可以使代码更易于维护,请告诉我。
  • weblogs.asp.net/scottgu/… 这似乎是更少更简洁的代码......所有的复杂性都被隐藏起来了,你不必维护它。
  • 我想这段代码不会处理不可为空的类型。是否有一个著名的解决方案只考虑跳过不可为空的类型?