【问题标题】:Create expression trees that calls a method with nullable type创建调用具有可空类型的方法的表达式树
【发布时间】:2020-01-09 10:51:40
【问题描述】:

我想通过使用表达式树来实现这个结果:

x.DataMod == null ? string.Empty : x.DataMod.Value.ToShortDateString()

我正在尝试使用Expression.Condition,但我不知道如何调用ToShortDateString()

我需要 Linq GroupBy 查询中的结果。

var grouped = context.Receipt.GroupBy(x => (x.DataMod == null ? string.Empty : x.DataMod.Value.ToShortDateString()) + ";" + x.DataOraDocumento.ToShortDateString() + ";" + x.Cassa.Descrizione + ";" + x.Sezionale.Descrizione).ToList();

谢谢

【问题讨论】:

  • 这只是一个和其他方法一样的方法调用 :)
  • 使用Value 属性(Expression.Property(nullable_expr, "Value"))代替nullable_expr

标签: c# expression-trees


【解决方案1】:

按照 cmets 中的建议,您应该使用 Expression.CallToShortDateString 方法调用创建表达式。我为原始表达式的略微简化版本编写了一个示例。见内联 cmets。

x.DataMod.HasValue ? x.DataMod.Value.ToShortDateString() : string.Empty

void Main()
{
    var now = DateTime.UtcNow;
    var tomorrow = now.AddDays(1);

    var data = new Test[] {
        new Test { DataMod = null },
        new Test { DataMod = now },
        new Test { DataMod = null },
        new Test { DataMod = tomorrow },
        new Test { DataMod = null },
        new Test { DataMod = now }
    };

    var keySelector = BuildSelector();

    var groups = data
        .GroupBy(keySelector)
        .ToList();

    foreach (var group in groups)
    {
        Console.WriteLine($"Group = \"{group.Key}\"");
        Console.WriteLine($"Items = {group.Count()}");
        Console.WriteLine();
    }
}

class Test
{
    public DateTime? DataMod { get; set; }
}

Func<Test, string> BuildSelector()
{
    // Builds delegate for the Expression: 
    // x => x.DataMod.HasValue ? x.DataMod.Value.ToShortDateString() : string.Empty

    // Expression for: x
    var x = Expression.Parameter(typeof(Test), "x");

    // Expression for: x.DataMod.HasValue
    var testExpr = Expression.Property(
        Expression.Property(
            x, 
            nameof(Test.DataMod)
        ),
        nameof(Nullable<DateTime>.HasValue)
    );

    // Expression for: x.DataMod.Value.ToShortDateString()
    var ifTrueExpr = Expression.Call(

        // Expression for: x.DataMod.Value
        Expression.Property(
            Expression.Property(
                x,
                nameof(Test.DataMod)
            ),
            nameof(Nullable<DateTime>.Value)
        ),

        // Expression for: ToShortDateString
        typeof(DateTime).GetMethod(
            nameof(DateTime.ToShortDateString)
        )

        /* args if any */
    );

    // Expression for: string.Empty
    var ifFalseExpr = Expression.Field(
        null,
        typeof(string).GetField(nameof(string.Empty))
    );

    // Expression for: x => x.DataMod.HasValue ? x.DataMod.Value.ToShortDateString() : string.Empty
    var conditionExpr = Expression.Condition(
        testExpr, 
        ifTrueExpr, 
        ifFalseExpr);

    // Compile to a delegate
    var lambda = Expression.Lambda<Func<Test, string>>(conditionExpr, x);
    return lambda.Compile();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 2011-12-16
    • 1970-01-01
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多