组合表达式

本文关键字:表达式 组合 | 更新日期: 2023-09-27 18:25:07

我是使用表达式的新手,在我正在处理的一个示例中遇到了一些问题。

我试图实现的是创建一个包含2个(或多个)表达式的表达式。

例如:

public static Expression<Func<Occurrence, bool>> ReporterStartsWithAndClosed()
{
    ParameterExpression occPar = Expression.Parameter(typeof(Occurrence));
    MemberExpression recorderProp = Expression.Property(occPar, "Reporter");
    MemberExpression fullnameProp = Expression.Property(recorderProp, "FullName");
    ConstantExpression letter = Expression.Constant("A", typeof(string));
    MethodInfo miStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    MethodCallExpression mCall = Expression.Call(fullnameProp, miStartsWith, letter);
    MemberExpression oiProp = Expression.Property(occPar, "OccurrenceIncident");
    MemberExpression statusProp = Expression.Property(oiProp, "OccurreceIncidentStatus");
    MemberExpression nameProp = Expression.Property(statusProp, "Name");
    ConstantExpression name = Expression.Constant("Closed", typeof(string));
    BinaryExpression equalTo = Expression.Equal(name, nameProp);
    return ...?
}

我的问题是,如何将这些表达式组合起来,以返回该方法的正确类型。即,将mCall和equalTo表达式的逻辑组合在一起的语法是什么。

我最初的想法是应该使用BlockExpressions,但我无法实现。

如有任何帮助,我们将不胜感激。

谢谢David

组合表达式

因此,要进行逻辑AND运算,请使用AndAlso()方法生成表达式。然后,为了完成您的方法,您需要将这个组合方法放入lambda表达式中。

只是一些提示,我会避免在声明中写出类型,这会使所有内容都更难阅读。此外,您可以通过使用Call()的此重载按名称调用方法,因此无需获取该方法的MethodInfo对象。

我会这样把它放在一起(未经测试):

public static Expression<Func<Occurrence, bool>> ReporterStartsWithAndClosed(
    string letter = "A")
{
    // occurrence =>
    //      occurrence.Reporter.FullName.StartsWith("A")
    //
    //      occurrence.OccurrenceIncident.OccurrenceIncidentStatus.Name == "Closed"
    var occurrence = Expression.Parameter(typeof(Occurrence), "occurrence");
    var reporter = Expression.Property(occurrence, "Reporter");
    var fullName = Expression.Property(reporter, "FullName");
    var startsWithLetter = Expression.Call(
        fullName,
        "StartsWith",
        null,
        Expression.Constant(letter, typeof(string))
    );
    var incident = Expression.Property(occurrence, "OccurrenceIncident");
    var status = Expression.Property(incident, "OccurrenceIncidentStatus");
    var name = Expression.Property(status, "Name");
    var equalsClosed = Expression.Equal(
        name,
        Expression.Constant("Closed", typeof(string))
    );
    var body = Expression.AndAlso(startsWithLetter, equalsClosed);
    return Expression.Lambda<Func<Occurrence, bool>>(body, occurrence);
}