2010-07-07 75 views
2

我有一個謂詞,它是在服務完所有擴展方法後由lambda表達式生成的。例如:Linq表達式替換參數類型

(new List<string>).Where(i => i.Contains("some")).Where(i => i.Contains("second_some")); 

「列表<>」僅僅是舉例來說,有可能是我的自定義數據上下文或對象的集合。所以,我有一個「Expression < ...>」,它是基本類型「Expression」。

問題是,是否有任何代碼可以遍歷表達式樹,並將另一個指定的參數類型(在我們的示例中是「string」)替換?

我已經找到了如何替換參數類型,但是當「Where」擴展方法有一箇舊參數類型簽名的方法時,它會產生衝突。

也許有人遇到了解決方案? 謝謝。

+0

目前還不清楚你在這種情況下想要做什麼......無論你做什麼,「一些」都將是一個字符串,那麼如果你轉換爲使用(比如說)'int '?例如, – 2010-07-07 14:16:39

+0

沒有「字符串」,而是「IUser」接口,並且linq2sql正在使用類來構建SQL字符串,所以它需要一個類「User」。因此,我需要將IUser替換爲用戶 – 2010-07-07 14:40:22

+0

您是否正在構建一個在運行時不知道該類型的表達式,並且希望編寫一個lamba'模板'方法? – 2010-07-08 22:42:23

回答

-1

表達式是不可變的類型。 要替換參數(及其類型),您應該使用原始表達式的主體創建一個新表達式,並傳遞要使用的參數。

  var resultingIQueryable = (new List<string>()).AsQueryable<string>().Where (i => i.Contains ("some")).Where (i => i.Contains ("second_some")); 

      // the Queryable.Where is a MethodCallExpression 
      var expressionOriginal = resultingIQueryable.Expression as MethodCallExpression; 
      // there are multiple where calls, this makes it all a little bit more confusing. 
      // The linq tree is built 'backwards' 
      // the first parameter of the expression is a MethodCallExpression: 
      // {System.Collections.Generic.List`1[System.String].Where(i => i.Contains("some"))} 
      // the second parameter: 
      // {i => i.Contains("second_some")} 
      // 
      // disecting the first parameter you will again find 2 parameters: 
      // {System.Collections.Generic.List`1[System.String]} 
      // {i => i.Contains("some")} 

使用linq(method)語法構建表達式然後走樹建立一個新表達式並不是一個好習慣。 如果我是你,我會嘗試使用Expression.Call &來構建表達式。Expression.Lambda & Expression.Paremeter ...語法。