Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Expression.GreaterThan在一个操作数为可空类型,另一个操作数为不可空类型时失败_C#_.net_C# 3.0 - Fatal编程技术网

C# Expression.GreaterThan在一个操作数为可空类型,另一个操作数为不可空类型时失败

C# Expression.GreaterThan在一个操作数为可空类型,另一个操作数为不可空类型时失败,c#,.net,c#-3.0,C#,.net,C# 3.0,我正在创建一些动态linq,但遇到以下问题: 二元运算符大于或等于 未为类型定义 'System.Nullable'1[System.DateTime]' 和“系统日期时间” 我明白为什么了,因为我的字段类型是可以为空的,我现在本质上是在传递DateTime 所以在试图解决这个问题的过程中,我尝试了 System.Nullable<DateTime> now; now = DateTime.Now; 我不确定您的代码到底是什么,但要获得可为null的不可为null的版本,请调用其.

我正在创建一些动态linq,但遇到以下问题:

二元运算符大于或等于 未为类型定义 'System.Nullable'1[System.DateTime]' 和“系统日期时间”

我明白为什么了,因为我的字段类型是可以为空的,我现在本质上是在传递DateTime

所以在试图解决这个问题的过程中,我尝试了

System.Nullable<DateTime> now;
now = DateTime.Now;

我不确定您的代码到底是什么,但要获得可为null的不可为null的版本,请调用其
.Value
成员。

在任何比较位置,按如下方式更改比较:

(nullableDT >= DT)

编辑:

根据您的注释,编写一个包含2个对象的函数,在函数内部检查它们是否为可空类型,并检查是否为空,然后比较值。此函数可能会使用类似于^的代码

不过,这听起来好像你有一个更大的潜在问题。要么您得到了不正确的数据(即,您在其他地方的代码返回的数据不应该是错误的,不是代码中的问题,而是逻辑中的问题),要么您可以比较这些对象的假设是无效的。这又是一个逻辑错误

我想你可能需要在这件事上退一步。如果您发布更多的代码,我们可能会为您提供更多帮助。

这很有趣

我尝试了这两种代码的变体:

    System.Nullable<DateTime> now = new System.Nullable<DateTime>();
    now = DateTime.Now;
System.Nullable now=new System.Nullable();
现在=日期时间。现在;

系统。现在可以为空;
现在=日期时间。现在;
他们两人都工作得很顺利

然后我重读你的问题。实际上,答案仍然是“值”属性。初始化变量(如果可以),但如果这样做:


(现在>=DateTime.now)在Linq查询中,您将得到一个错误。它应该是(now.Value>=DateTime.now)

这里的问题是,当给定两个不匹配的nullability参数时,表达式库会引发异常。这里有一个简单的复制:

Expression<Func<DateTime?>> ex1 = ()=>DateTime.Now;
Expression<Func<DateTime>> ex2 = ()=>DateTime.Now;
var ex3 = Expression.GreaterThan(ex1.Body, ex2.Body);
表达式ex1=()=>DateTime.Now;
表达式ex2=()=>DateTime.Now;
var ex3=Expression.GreaterThan(ex1.Body,ex2.Body);
我不清楚这是否是一个bug;C#的规则要求在这种情况下,将不可为null的操作数转换为可为null的操作数,并使用提升为可为null的比较形式。但是,表达式树库不需要遵循C#的规则,因为表达式树库当然可以用来表示C#表达式、Python表达式、JScript表达式、VB表达式等;它不可能遵循所有可能语言的所有规则

但无论如何,这看起来可能是一个bug,所以我将把它提交给表达式树团队,看看他们怎么说。同时,您可以通过定义自己的帮助器方法来修复操作数,从而轻松解决此问题。一个速写应该是:

    static Expression MyGreaterThan(Expression e1, Expression e2)
    {
        if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
            e2 = Expression.Convert(e2, e1.Type);
        else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
            e1 = Expression.Convert(e1, e2.Type);
        return Expression.GreaterThan(e1, e2);
    }
    static bool IsNullableType(Type t)
    {
        return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
    }
静态表达式MyGreaterThan(表达式e1、表达式e2)
{
if(IsNullableType(e1.Type)&&!IsNullableType(e2.Type))
e2=表达式.Convert(e2,e1.Type);
如果(!IsNullableType(e1.Type)和&IsNullableType(e2.Type))
e1=表达式.Convert(e1,e2.Type);
返回表达式。大于(e1,e2);
}
静态bool IsNullableType(类型t)
{
返回t.IsGenericType&&t.GetGenericTypeDefinition()==typeof(可为null);
}

但是,请注意,这并不能检查e1和e2的类型是否仅在可空性方面不同;如果传入一个可为Null的int和一个不可为Null的double表达式,就会发生不好的事情。我把它作为一个练习,以实现更好的逻辑,检查这两个表达式的类型是否只有可为Null性不同。

我找到了一个在.Net framework中工作的解决方案。这里有一个方法仍在进行中,但它确实有效,并且适用于Linq to实体:

public PagedViewModel<T> Filter<TValue>(Expression<Func<T, TValue>> predicate, FilterType filterType = FilterType.Equals) {
        var name = (predicate.Body as MemberExpression ?? ((UnaryExpression)predicate.Body).Operand as MemberExpression).Member.Name;            
        var value = Expression.Constant(ParamsData[name].To<TValue>(), typeof (T).GetProperty(name).PropertyType);                        

        // If nothing has been set for filter, skip and don't filter data.
        ViewData[name] = m_QueryInternal.Distinct(predicate.Compile()).ToSelectList(name, name, ParamsData[name]);
        if (string.IsNullOrWhiteSpace(ParamsData[name]))
            return this;

        var nameExpression = Expression.Parameter(typeof(T), name);
        var propertyExpression = Expression.Property(nameExpression, typeof(T).GetProperty(name));

        // Create expression body based on type of filter
        Expression expression;
        MethodInfo method;
        switch(filterType) {
            case FilterType.Like:
                method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                expression = Expression.Call(propertyExpression, method, value); 
                break;
            case FilterType.EndsWith:
            case FilterType.StartsWith:
                method = typeof(string).GetMethod(filterType.ToString(), new[] { typeof(string) });
                expression = Expression.Call(propertyExpression, method, value);
                break;
            case FilterType.GreaterThan:
                expression = Expression.GreaterThan(propertyExpression, value);                    
                break;
            case FilterType.Equals:
                expression = Expression.Equal(propertyExpression, value);
                break;
            default:
                throw new ArgumentException("Filter Type could not be determined");
        }            

        // Execute the expression against Query.
        var methodCallExpression = Expression.Call(
            typeof (Queryable),
            "Where",
            new[] { Query.ElementType },
            Query.Expression,
            Expression.Lambda<Func<T, bool>>(expression, new[] { nameExpression }));

        // Filter the current Query data.
        Query = Query.Provider.CreateQuery<T>(methodCallExpression);            

        return this;
    }
publicpagedviewmodel过滤器(表达式谓词,FilterType FilterType=FilterType.Equals){
变量名称=(predicate.Body作为MemberExpression??((UnaryExpression)predicate.Body)。操作数作为MemberExpression)。Member.name;
var value=Expression.Constant(ParamsData[name].To(),typeof(T).GetProperty(name).PropertyType);
//如果未为筛选设置任何内容,请跳过并不筛选数据。
ViewData[name]=m_QueryInternal.Distinct(predicate.Compile()).ToSelectList(name,name,ParamsData[name]);
if(string.IsNullOrWhiteSpace(ParamsData[name]))
归还这个;
var nameExpression=Expression.Parameter(typeof(T),name);
var propertyExpression=Expression.Property(nameExpression,typeof(T).GetProperty(name));
//基于筛选器类型创建表达式正文
表达;
方法信息法;
开关(过滤器类型){
案例筛选器类型。例如:
method=typeof(string).GetMethod(“Contains”,new[]{typeof(string)});
expression=expression.Call(propertyExpression、方法、值);
打破
案例过滤器type.EndsWith:
案例过滤器type.StartsWith:
method=typeof(string).GetMethod(filterType.ToString(),new[]{typeof(string)});
expression=expression.Call(propertyExpression、方法、值);
打破
案例过滤器类型。大于:
expression=expression.GreaterThan(propertyExpression,value);
打破
案例过滤器类型。等于:
expression=expression.Equal(propertyExpression,value);
打破
违约:
抛出新ArgumentException(“无法确定筛选器类型”);
}            
//对查询执行表达式。
var methodCallExpr
Expression<Func<DateTime?>> ex1 = ()=>DateTime.Now;
Expression<Func<DateTime>> ex2 = ()=>DateTime.Now;
var ex3 = Expression.GreaterThan(ex1.Body, ex2.Body);
    static Expression MyGreaterThan(Expression e1, Expression e2)
    {
        if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
            e2 = Expression.Convert(e2, e1.Type);
        else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
            e1 = Expression.Convert(e1, e2.Type);
        return Expression.GreaterThan(e1, e2);
    }
    static bool IsNullableType(Type t)
    {
        return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
    }
public PagedViewModel<T> Filter<TValue>(Expression<Func<T, TValue>> predicate, FilterType filterType = FilterType.Equals) {
        var name = (predicate.Body as MemberExpression ?? ((UnaryExpression)predicate.Body).Operand as MemberExpression).Member.Name;            
        var value = Expression.Constant(ParamsData[name].To<TValue>(), typeof (T).GetProperty(name).PropertyType);                        

        // If nothing has been set for filter, skip and don't filter data.
        ViewData[name] = m_QueryInternal.Distinct(predicate.Compile()).ToSelectList(name, name, ParamsData[name]);
        if (string.IsNullOrWhiteSpace(ParamsData[name]))
            return this;

        var nameExpression = Expression.Parameter(typeof(T), name);
        var propertyExpression = Expression.Property(nameExpression, typeof(T).GetProperty(name));

        // Create expression body based on type of filter
        Expression expression;
        MethodInfo method;
        switch(filterType) {
            case FilterType.Like:
                method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                expression = Expression.Call(propertyExpression, method, value); 
                break;
            case FilterType.EndsWith:
            case FilterType.StartsWith:
                method = typeof(string).GetMethod(filterType.ToString(), new[] { typeof(string) });
                expression = Expression.Call(propertyExpression, method, value);
                break;
            case FilterType.GreaterThan:
                expression = Expression.GreaterThan(propertyExpression, value);                    
                break;
            case FilterType.Equals:
                expression = Expression.Equal(propertyExpression, value);
                break;
            default:
                throw new ArgumentException("Filter Type could not be determined");
        }            

        // Execute the expression against Query.
        var methodCallExpression = Expression.Call(
            typeof (Queryable),
            "Where",
            new[] { Query.ElementType },
            Query.Expression,
            Expression.Lambda<Func<T, bool>>(expression, new[] { nameExpression }));

        // Filter the current Query data.
        Query = Query.Provider.CreateQuery<T>(methodCallExpression);            

        return this;
    }
var paramsData = new NameValueCollection { { "CreatedOn", DateTime.Today.ToString() } };
        var model = m_data.ToPagedList(new ViewDataDictionary(), paramsData, 1, 10, null, x => x.LastName)
                          .Filters(Criteria<TrainerProfile>.New(x => x.CreatedOn, FilterType.GreaterThan))
                          .Setup();