简体   繁体   English

使用!DateTime.HasValue创建表达式树

[英]Creating an Expression Tree with !DateTime.HasValue

I have a very large expression tree builder that has been built and added to regularly as new functionality was needed. 我有一个非常大的表达式树生成器,可以根据需要添加并定期添加新功能。 It has been working perfectly for all types including Nullable<> types. 它对所有类型(包括Nullable <>类型)都运行良好。 Several of my Nullable<> types are DateTime as those columns in my database allow nulls. 我的Nullable <>类型中有几种类型是DateTime,因为数据库中的那些列允许为空。

Now, I need to adjust the method to be able to filter based on a DateTime having ANY value. 现在,我需要调整方法以能够基于具有ANY值的DateTime进行过滤。 In SQL terms: 用SQL术语:

WHERE date_Column IS NOT NULL

In LINQ terms: 用LINQ术语:

.Where(s => !s.date_column.HasValue)

For the life of me, I cannot figure out how to add this to my expression tree. 对于我的一生,我无法弄清楚如何将其添加到表达式树中。 I can add any operator to the MyFilter class that I like, so if a new case will help, that is no problem. 我可以将任何运算符添加到我喜欢的MyFilter类中,因此,如果有新的案例有用,那就没问题了。

Below is the builder cut down to just the DateTime portion for readability. 下面是构建器,出于可读性考虑,它仅缩减到DateTime部分。

public class MyFilter
{
    public string FieldName { get; set; }
    public string FieldValue { get; set; }
    public string Operator { get; set; }
}

private Expression<Func<MyDTO, bool>> CreateLambda(MyFilter myFilter)
{
    ParameterExpression parameter = Expression.Parameter(typeof(MyDTO), "m");
    Expression property = Expression.Property(parameter, myFilter.FieldName);
    Expression target = null;
    Expression exp = null;
    PropertyInfo pi = null;
    MethodInfo mi = null;

    var switchType = property.Type.ToString();

    switch (switchType)
    {
        case "System.DateTime":
            target = (myFilter.FieldValue == "null") ?
                Expression.Constant(null, property.Type) :
                Expression.Constant(Convert.ToDateTime(myFilter.FieldValue));
            switch (myFilter.Operator)
            {
                case "eq":
                    exp = Expression.Equal(property, Expression.Convert(target, property.Type));
                    break;
                case "ne":
                    exp = Expression.NotEqual(property, Expression.Convert(target, property.Type));
                    break;
                case "ge":
                    exp = Expression.GreaterThanOrEqual(property, Expression.Convert(target, property.Type));
                    break;
                case "gt":
                    exp = Expression.GreaterThan(property, Expression.Convert(target, property.Type));
                    break;
                case "le":
                    exp = Expression.LessThanOrEqual(property, Expression.Convert(target, property.Type));
                    break;
                case "lt":
                    exp = Expression.LessThan(property, Expression.Convert(target, property.Type));
                    break;
            }
            break;
    }
    Expression<Func<MyDTO, bool>> lambda = Expression.Lambda<Func<MyDTO, bool>>(exp, parameter);
    return lambda;
}

Filip Cordas was correct and both his statements produce the same correct result. 菲利普·科尔达斯(Filip Cordas)是正确的,他的两句话都得出了正确的结果。 I have no idea why Expression.NotEquals was not working for me yesterday, but the code above does work as is. 我不知道为什么Expression.NotEquals昨天对我不起作用,但是上面的代码仍然可以正常工作。

However, since my question was about how to use the HasValue property of a Nullable, I appreciated Filip's second answer very much. 但是,由于我的问题是关于如何使用Nullable的HasValue属性的,所以我非常感谢Filip的第二个答案。 Also, now that I see it, it is humbling that I could not get it myself. 另外,现在我看到了,我自己也无法获得它,这令人感到沮丧。

The code I implemented to use the HasValue within my environment looks like the following: 我为在环境中使用HasValue而实现的代码如下所示:

public class MyFilter
{
    public string FieldName { get; set; }
    public string FieldValue { get; set; }
    public string Operator { get; set; }
}

private Expression<Func<MyDTO, bool>> CreateLambda(MyFilter myFilter)
{
    ParameterExpression parameter = Expression.Parameter(typeof(MyDTO), "m");
    Expression property = Expression.Property(parameter, myFilter.FieldName);
    Expression target = null;
    Expression exp = null;
    PropertyInfo pi = null;
    MethodInfo mi = null;

    var switchType = property.Type.ToString();

    switch (switchType)
    {
        case "System.DateTime":
            target = (myFilter.FieldValue == "null") ?
                Expression.Constant(null, property.Type) :
                Expression.Constant(Convert.ToDateTime(myFilter.FieldValue));
            switch (myFilter.Operator)
            {
                case "eq":
                    exp = Expression.Equal(property, Expression.Convert(target, property.Type));
                    break;
                case "ne":
                    if (myFilter.FieldValue == "null")
                    {
                        exp = Expression.Property(property, "HasValue");
                    }
                    else
                    {
                        exp = Expression.NotEqual(property, Expression.Convert(target, property.Type));
                    }
                    break;
                case "ge":
                    exp = Expression.GreaterThanOrEqual(property, Expression.Convert(target, property.Type));
                    break;
                case "gt":
                    exp = Expression.GreaterThan(property, Expression.Convert(target, property.Type));
                    break;
                case "le":
                    exp = Expression.LessThanOrEqual(property, Expression.Convert(target, property.Type));
                    break;
                case "lt":
                    exp = Expression.LessThan(property, Expression.Convert(target, property.Type));
                    break;
            }
            break;
    }
    Expression<Func<MyDTO, bool>> lambda = Expression.Lambda<Func<MyDTO, bool>>(exp, parameter);
    return lambda;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM