2010-07-07 92 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 ...语法。