2015-07-10 76 views
2

創建(波長)的表達,我有以下解釋:使用遞歸

Dictionary<string, PropertyInfo> filterProperties; 

這本字典的內容可以是這樣的:

- "Language": [QueryData.Lang], 
- "Id": [Querydata.UserId] 

每個字符串的一個屬性鍵映射我的QueryData類型。

現在讓我們假設我有以下QueryData實例:

QueryData: { Lang= "en", UserId = "mcicero" } 

使用以前的字典作爲例子,我想建立以下表達式:

e => e.Language == "en" && e.Id == "mcicero"; 

正如你所看到的字典鍵用於訪問e的屬性,字典值(QueryData屬性)用於指定二進制平等表達式中的常量。

eEntity類型,並保證具有此屬性。

所得的表達應該是類型Expression<Func<Entity, bool>>

如何建立使用遞歸這體現在哪裏?

我說遞歸,因爲它聽起來像是一個自然的解決方案,但迭代的將是首選。

我嘗試了迭代的替代方法,最後得到了一個醜陋的,不容易理解的代碼。

但是,我無法爲此問題創建遞歸方法。

+0

您可能想要使用動態LINQ。這裏有一些信息http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library – DLeh

+1

您可能需要查看[表達式樹](https:/ /msdn.microsoft.com/en-us/library/bb397951.aspx)。 – npinti

+0

忽略所有字典和QueryData的東西,你只是想知道如何在運行時從'PropertyInfo'和一個字符串創建一個像'e => e.Language =「en」'這樣的表達式。 –

回答

3

離開個人表達你的創作,只是在迭代循環相結合他們:

// For an IEnumerable<Expression> in "expressions" 
Expression left = null; 
foreach(var right in expressions) 
{ 
    if(left == null) 
    left = right; 
    else 
    left = Expression.And(left, right); 
} 
// Combined expression is in "left" 
// Don't forget it will be null if there were no expressions provided... 

或與LINQ一行:

var expr = expressions.Aggregate(Expression.And); 
+0

謝謝你那一行的LINQ聲明!美麗! –

+0

這會導致樹儘可能深,當節點很多時會降低性能。您應該嘗試構建一個儘可能平坦的樹,例如將它們放入隊列中,取出前兩個元素,並將它們放在最後,直到只剩下一個節點。 – MBoros

2

對於感興趣的,在一條線:

Expression expr = filterProperties.Select(i => Expression.Equal(
                Expression.Property(entityParameter, i.Key), 
                Expression.Constant(i.Value.GetValue(queryObj)) 
             )).Aggregate(Expression.And);