C# 重构 lambda 表达式
我有几个共享属性的 Expression
表达式。例如,
Expression<Func<User, bool>> e1 =
(User u) => u.IsActive && u.Group != "PROCESS" && u.Name != null;
Expression<Func<User, bool>> e2 =
(User u) => u.IsActive && u.Group != "PROCESS" && u.Name != "A";
Expression<Func<User, bool>> e3 =
(User u) => u.IsActive && u.Group != "PROCESS" && u.Name != "B";
是否有一种简单的方法可以将 u.IsActive && u.Group != "PROCESS"
在变量中并在 e1、e2 和 e3 中使用它?编辑:我仍然想要同一棵树。
似乎我可以通过使用 Expression.Lambda
等...) 构建表达式来做到这一点,但它并没有简化我的代码,而是使读。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我相信没有更干净的方法可以为您的案例做到这一点。您可以使用
BinaryExpression
正如您所提到的。您可以将BinaryExpression
和Expression.Lambda
调用封装到一个方法中并调用该方法(例如 PredicateBuilder.And),但在我看来,这些都不像当前语法那么干净。I believe there's no cleaner way to do that for your case. You can use
BinaryExpression
as you mentioned. You can encapsulate theBinaryExpression
andExpression.Lambda
calls into a method and call that instead (like PredicateBuilder.And) but none of those are as clean as the current syntax IMO.lambda 表达式的问题在于它们是不可变的,并且您无法轻松替换 lambda 的参数。我最初的想法是做这样的事情(不幸的是,这不会成功):
并在代码中使用:
可能的解决方案
您可以尝试使用旨在实现表达式生成器的项目之一。我没有使用过其中任何一个,但谷歌提供了大量链接,例如:
另一种方法
,如果您是在 LINQ 中使用这些表达式来过滤值,您可以使用不同的方法(不要组合表达式,而是组合过滤器):
Problem with lambda expressions is that they are immutable and you can't easily replace parameters of lambda. My original idea was to do something like this (unfortunately, this won't work out):
and use in code:
Possible solution
You can try to use one of the project aiming on implementing expression builders. I haven't used any of them but google gives plenty of links, for example:
Another approach
If you are using these expressions in LINQ to filter values, you can user different approach (don't combine expressions but combine filters):
我认为不一定有比您已经使用的答案更好的答案。正如 Mehrdad 提到的,您必须使用 BinaryExpression 构建更深的树,我认为这将是当前代码可读性的倒退。
根据您的使用情况,您可能可以通过利用闭包语义并执行以下操作来节省一些代码行:
...但是这是否有任何用途将取决于您对已编译的委托。可能对你来说完全没用,但值得一提以防万一!
I don't think that there's necessarily a better answer than the one which you're using already. As Mehrdad mentions, you'll have to build a deeper tree using a BinaryExpression and I think that would be a step backwards in readability from your current code.
Depending on your usage, you might be able to save some lines of code by exploiting closure semantics and doing something like this:
...but whether that's any use will depend on what you're doing with the compiled delegate. May be entirely useless to you but worth a mention just in case!