【问题标题】:Expression.Equal - How to Compare Nullable and Non Nullable fields?Expression.Equal - 如何比较 Nullable 和 Non Nullable 字段?
【发布时间】:2013-05-17 02:54:10
【问题描述】:

我有一个可以为空的datetime 字段,我必须将string 日期字段转换为可以为空的日期时间类型(使用Expression)....我使用下面的方法进行了此操作。

 Expression.Constant(Convert.ChangeType(value, Nullable.GetUnderlyingType(memberAccess.Type)));.

memberAccess(上面提到的)是成员表达式类型。 (来自 LinqExtensions.cs) 现在在代码中我使用的是 Expression.Equal 方法。

Expression.Equal(memberAccess, filter); 

这里失败了,因为 memberaccess 类型可以为空,但 filter.type 不能为空...

即使我尝试使用

将成员访问类型转换为可为空
ConstantExpression test = Expression.Constant(Nullable.GetUnderlyingType(memberAccess.Type)),

Type 是 Runtime 而不是 DateTime。

如何使用Expression.Equal 比较可空字段和不可空字段?有没有办法将字符串类型转换为可为空的日期时间字段?其中任何一个都可以解决我的问题。

【问题讨论】:

  • 在此处发布您的一些代码。
  • 您是否有只能使用Expression的限制?

标签: c# linq lambda expression linq-extensions


【解决方案1】:

好的..我就是这样做的。

首先转换类型(字符串到日期时间)

filter = Expression.Constant(
    Convert.ChangeType(value, memberAccess.Type.GetGenericArguments()[0]));

然后将此表达式转换为所需的类型

Expression typeFilter = Expression.Convert(filter, memberAccess.Type);

然后用Expression.Equal(memberAccess, typeFilter)...

memberAccess is MemberExpression,它从模型中获取属性类型)

【讨论】:

    【解决方案2】:

    如果您有除日期以外的可为空值,这就是您可以为可空类型创建表达式树的方法,假设您有一个可为空字段 BoardId,您可以像这样动态创建表达式树

    var nameValue="BoardId=111";

     public static Expression<Func<T, bool>> BuildWhereExpression<T>(string nameValueQuery ) where  T : class 
            {
                Expression<Func<T, bool>> predicate = null;
                PropertyInfo prop = null;
                var fieldName = nameValueQuery.Split("=")[0];
                var fieldValue = nameValueQuery.Split("=")[1];
                var properties = typeof(T).GetProperties();
                foreach (var property in properties)
                {
                    if (property.Name.ToLower() == fieldName.ToLower())
                    {
                        prop = property;
                    }
                } 
                if (prop != null)
                {
                    var isNullable = prop.PropertyType.IsNullableType();
                    var parameter = Expression.Parameter(typeof(T), "x");
                    var member = Expression.Property(parameter, fieldName); 
    
                    if (isNullable)
                    {
                        var filter1 =
                            Expression.Constant(
                                Convert.ChangeType(fieldValue, member.Type.GetGenericArguments()[0]));
                        Expression typeFilter = Expression.Convert(filter1, member.Type);
                        var body = Expression.Equal(member, typeFilter);  
                        predicate = Expression.Lambda<Func<T, bool>>(body, parameter);  
                    }
                    else
                    {
                        if (prop.PropertyType == typeof(string) && likeOerator.ToLower() == "like")
                        {
                            var parameterExp = Expression.Parameter(typeof(T), "type");
                            var propertyExp = Expression.Property(parameterExp, prop);
                            MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                            var someValue = Expression.Constant(fieldValue, typeof(string));
                            var containsMethodExp = Expression.Call(propertyExp, method, someValue);
                            predicate = Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
                        }
                        else
                        {
                            var constant = Expression.Constant(Convert.ChangeType(fieldValue, prop.PropertyType));
                            var body = Expression.Equal(member, constant);  
                            predicate = Expression.Lambda<Func<T, bool>>(body, parameter); `enter code here`
                        }
                    }
                }
                return predicate;
            }
    

    1- 此解决方案首先检查 Nullable 值并生成表达式。 这是您如何确定类型是否为 Nullable 的方法。为此,我创建了一个扩展方法

    public static bool IsNullableType(this Type type)
        {
            return type.IsGenericType && (type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
        }
    

    2-第二步是检查类型,如果它的字符串,然后为字符串创建一个表达式。

    3-第三步是检查值是不是可以为空的不是字符串然后使用等于创建一个表达式

    【讨论】:

    【解决方案3】:

    您应该使用DateTime.Parse 或者更好的是DateTime.ParseExact 将您的字符串转换为日期。所以,Expression.Call

    如果要在字符串为空的情况下将其转换为空日期,可以使用Expression.Condition
    如果你想让结果可以为空,我相信Expression.Convert 可以做到。

    类似(伪代码):

    Condition(
        Equals(yourStringExpression, null),
        Constant(null, typeof(DateTime?)),
        Convert(
            Call(DateTime.ParseExact, yourStringExpression, ...),
            typeof(DateTime?)
        )
    )
    

    【讨论】:

      【解决方案4】:

      您可以在Expression.Constant中传递Type:

      ConstantExpression constant = Expression.Constant(value, member.Type);
      BinaryExpression equalExpression = Expression.Equal(member, constant);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-07
        • 2023-03-31
        • 2021-09-27
        相关资源
        最近更新 更多