Expression.Equal - 如何比较Nullable和Non Nullable字段?

时间:2013-05-17 02:54:10

标签: c# linq lambda expression linq-extensions

我有一个可空的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来比较nullable&不可空的领域?有没有办法将字符串类型转换为可空的日期时间字段?其中任何一个都可以解决我的问题。

3 个答案:

答案 0 :(得分:5)

好的..我这样做了。

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

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

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

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

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

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

答案 1 :(得分:0)

您应该使用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?)
    )
)

答案 2 :(得分:0)

如果你有值为Nullable值而不是日期,这就是你可以为可空类型创建表达式树的方法,假设你有一个可以为空的字段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-第三步是检查值是否为空而不是字符串然后使用相等

创建表达式