2012-02-17 88 views
1

我是新來使用表達式,我正在通過一個示例中遇到一些問題。組合表達式

我想要實現的是創建一個表達式,其中有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,但我無法得到這個工作。

任何幫助將不勝感激。

感謝 大衛

+0

我應該也說,我知道這可能與Expresion.And()來完成。如果你有很多表情,我的問題更多的是你做什麼。有沒有更優雅的方式來組合這些? – 2012-02-17 09:26:19

回答

1

所以做邏輯與,使用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); 
}