代码之家  ›  专栏  ›  技术社区  ›  olivierr91

强制将datetimeoffset转换为nullable<datetimeoffset>

  •  1
  • olivierr91  · 技术社区  · 6 年前

    我需要编写一个动态构建LINQ查询表达式的函数。我无法建立一个 Equals 比较 DateTimeOffset 到A DateTimeOffset? ( Expression.Equal 抱怨类型无法进行比较),也无法转换 数据偏移 到A DateTimeOffset? 使 表达式.equal 工作,因为 数据偏移 无法转换为 DateTimeOffset? 不管我使用什么转换策略。

    MyEntity.cs:

    public class MyEntity {
        public DateTimeOffset? DeliverOn;
    }
    

    Main.cs:

    public void Test {
        IQueryable<MyEntity> MyEntityList = Enumerable.Empty<MyEntity>().AsQueryable();
        DateTimeOffset? dt1 = new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
        var expr = WhereEquals(MyEntityList, t => t.DeliverOn, dt1);
    }
    

    expressionbuilder.cs(表达式生成器.cs):

    public static IQueryable<TSource> WhereEquals<TSource, TValue>(IQueryable<TSource> source, Expression<Func<TSource, TValue>> selector, TValue value) {
        return source.Where(Expression.Lambda<Func<TSource, bool>>(Expression.Equal(selector.Body, Expression.Constant(value)), selector.Parameters));
    }
    

    投掷: System.InvalidOperationException: 'The binary operator Equal is not defined for the types 'System.Nullable``1[System.DateTimeOffset]' and 'System.DateTimeOffset'.'

    尽管 dt1 是一个 DateTimeOffset? 在编译时,在运行时,C认为 DT1 是一个 数据偏移 . 我能解决这个问题吗?

    我已经尝试过:

    • DateTimeOffset? dt1 = (DateTimeOffset?)new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
    • DateTimeOffset? dt1 = (DateTimeOffset?)(object)new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
    • DateTimeOffset? dt1 = (DateTimeOffset?)Convert.ChangeType(new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero), typeof());

    然而,DT1仍然是 数据偏移 .

    1 回复  |  直到 6 年前
        1
  •  2
  •   Dan Wilson    6 年前

    使用过载 Expression.Constant(Object, Type) 指定要在比较中使用的值的类型。

    不指定类型, Nullable<DateTimeOffset> 只是被打开 DateTimeOffset .

    void Main()
    {
        //IQueryable<MyEntity> MyEntityList = Enumerable.Empty<MyEntity>().AsQueryable();
        var MyEntityList = new List<MyEntity>();
        MyEntityList.Add(new MyEntity { DeliverOn = new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero) });
        DateTimeOffset? dt1 = new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
        var expr = WhereEquals<MyEntity, DateTimeOffset?>(MyEntityList.AsQueryable(), t => t.DeliverOn, (DateTimeOffset?)dt1);
        Console.WriteLine($"{expr.Count()} item(s) found");
    
        // Output:
        // selector.GetType() is System.Linq.Expressions.Expression`1[System.Func`2[UserQuery + MyEntity, System.Nullable`1[System.DateTimeOffset]]]
        // typeof(TValue) is System.Nullable`1[System.DateTimeOffset]
        // value.GetType() is System.DateTimeOffset
        // 1 item(s) found
    }
    
    public class MyEntity
    {
        public DateTimeOffset? DeliverOn;
    }
    
    public static IQueryable<TSource> WhereEquals<TSource, TValue>(IQueryable<TSource> source, Expression<Func<TSource, TValue>> selector, TValue value)
    {
        Console.WriteLine($"selector.GetType() is {selector.GetType()}");
        Console.WriteLine($"typeof(TValue) is {typeof(TValue)}");
        Console.WriteLine($"value.GetType() is {value.GetType()}");
        return source.Where(Expression.Lambda<Func<TSource, bool>>(Expression.Equal(selector.Body, Expression.Constant(value, typeof(TValue))), selector.Parameters));
    }
    

    相关,尽管接受的答案使用 Expression.Convert() 我认为这是不必要的。

    Working with nullable types in Expression Trees