2010-12-17 58 views
2

目標是從兩個LambdaExpressions獲取一個MemberExpressions數組。第一個可轉換爲返回對象實例的MethodCallExpression(Expression<Func<T>>)。第二個Lambda表達式將採用編譯的第一個表達式的結果並返回一個嵌套成員(Expression<Func<T,TMember>>)。我們可以假設第二個Lambda表達式只會調用嵌套屬性,但可能會執行其中幾個調用。MemberExpression to MemberExpression []

因此,該方法,我想創建的簽名是:

MemberExpression[] GetMemberExpressionArray<T,TValue>(Expression<Func<T>> instanceExpression, Expression<Func<T,TValue>> nestedMemberExpression)

其中nestedMemberExpression將被假定採取的形式

parent => parent.ChildProperty.GrandChildProperty

和的說法結果數組表示MemberAccess從parentChildProperty,並從ChildProperty到的值。

我已經使用以下擴展方法返回了最後的MemberExpression

public static MemberExpression GetMemberExpression<T, TValue>(Expression<Func<T, TValue>> expression) 
{ 
    if (expression == null) 
    { 
     return null; 
    } 
    if (expression.Body is MemberExpression) 
    { 
     return (MemberExpression)expression.Body; 
    } 
    if (expression.Body is UnaryExpression) 
    { 
     var operand = ((UnaryExpression)expression.Body).Operand; 
     if (operand is MemberExpression) 
     { 
      return (MemberExpression)operand; 
     } 
     if (operand is MethodCallExpression) 
     { 
      return ((MethodCallExpression)operand).Object as MemberExpression; 
     } 
    } 
    return null; 
} 

現在,我知道有幾種方法可以做到這一點。對我來說最直觀的將是循環訪問.Expression屬性,以獲取第一個表達式並捕獲每個MemberExpression的引用。這可能是最好的方法,但它可能不是。我對使用這樣的表達式得到的性能成本並不十分熟悉。我知道一個MemberExpression有一個MemberInfo,這個反射應該會影響性能。

我試圖搜索關於表達式的信息,但是我的資源在我發現的內容中非常有限。

我將不勝感激關於如何以最佳性能和可靠性完成此任務(以及此類任務,一般)的任何建議。

回答

1

我不知道爲什麼,這已被標記性能,但我能想到的從樹上提取成員表達了最簡單的方式是繼承ExpressionVisitor。這應該比手動編寫邏輯來「展開」不同類型的表達式並遍歷樹更簡單。

你很有可能要重寫VisitMember方法,以便:

  1. 每個成員表達被捕獲。
  2. 它的孩子被訪問。

我想象,看起來是這樣的:

protected override Expression VisitMember(MemberExpression node) 
{ 
    _myListOfMemberExpressions.Add(node); 
    return base.VisitMember(node); 
} 

我稍微弄不清你的任務的剩餘部分;它看起來像你想重寫參數表達式,在這種情況下,你可能想看看從Marc Gravell this answer