Linq 表达式替换参数类型

发布于 2024-09-08 16:02:02 字数 404 浏览 2 评论 0原文

我有一个谓词,它是在提供所有扩展方法后由 lambda 表达式组成的。例如:

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

“列表<>”只是示例,可能有我的自定义数据上下文或对象集合。所以,我有一个“表达式<...>”,它的基本类型“表达式”。

问题是,是否有任何代码可以遍历表达式树,并将参数类型(在我们的示例中为“字符串”)替换为另一个指定的类型?

我已经找到了如何替换参数类型,但是当“Where”扩展方法中的某个方法具有旧参数类型的签名时,它会发生冲突。

也许有人遇到过解决方案? 谢谢。

I have a predicate, that was made from lambda expression after all extension methods were served. For example:

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

"List<>" is only example, there could be my custom data context or object collection. So, I have an "Expression<...>", and it's base type "Expression".

The question is, is there are any code, which could walk the tree of expression, and replace parameter type (in our sample it is "string") with another one specified?

I have already found how to replace parameter type, but it has a conflict when the method somewhere from "Where" extension method has a signature with old parameter type.

Maybe someone has met solution?
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白云悠悠 2024-09-15 16:02:02

表达式是不可变类型。
要替换参数(及其类型),您应该使用原始表达式的主体创建一个新表达式,并传递您想要使用的参数。

            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(方法)语法构建表达式,然后遍历树来构建新表达式,这并不是一个好的做法。
如果我是你,我会尝试使用 Expression.Call & 构建表达式。表达式.Lambda &表达式.参数...语法。

An expression is an immutable type.
To replace parameters (and their type) you sould create a new expression using the body of the original expression, passing the parameters you want to use.

            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")}

It is not really a good practice to build expressions using linq (method) syntax and then walk the tree to build a new expression.
If i were you i would try to build the expression using Expression.Call & Expression.Lambda & Expression.Paremeter... syntax.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文