如何组合两个表达式?
我正在尝试构建一个将应用于 IQueryable 集合的表达式。
我可以构建这样的表达式:
[TestClass]
public class ExpressionTests
{
private IQueryable<MyEntity> entities;
private class MyEntity
{
public string MyProperty { get; set; }
}
[TestInitialize]
public void Setup()
{
entities = new[]
{
new MyEntity {MyProperty = "first"},
new MyEntity {MyProperty = "second"}
}.AsQueryable();
}
[TestMethod]
public void TestQueryingUsingSingleExpression()
{
Expression<Func<MyEntity, bool>> expression = e => e.MyProperty.Contains("irs");
Assert.AreEqual(1, entities.Where(expression).Count());
}
}
现在我想将表达式的两部分分开:
[TestMethod]
public void TestQueryingByCombiningTwoExpressions()
{
Expression<Func<MyEntity, string>> fieldExpression = e => e.MyProperty;
Expression<Func<string, bool>> operatorExpression = e => e.Contains("irs");
// combine the two expressions somehow...
Expression<Func<MyEntity, bool>> combinedExpression = ???;
Assert.AreEqual(1, entities.Where(combinedExpression).Count());
}
关于如何执行此操作有什么建议吗?
顺便说一句,将解析表达式的提供程序是 Linq for NHibernate。
I am trying to build up an expression that will be applied to an IQueryable collection.
I can build an expression like this:
[TestClass]
public class ExpressionTests
{
private IQueryable<MyEntity> entities;
private class MyEntity
{
public string MyProperty { get; set; }
}
[TestInitialize]
public void Setup()
{
entities = new[]
{
new MyEntity {MyProperty = "first"},
new MyEntity {MyProperty = "second"}
}.AsQueryable();
}
[TestMethod]
public void TestQueryingUsingSingleExpression()
{
Expression<Func<MyEntity, bool>> expression = e => e.MyProperty.Contains("irs");
Assert.AreEqual(1, entities.Where(expression).Count());
}
}
Now I want to separate the two parts of the expression:
[TestMethod]
public void TestQueryingByCombiningTwoExpressions()
{
Expression<Func<MyEntity, string>> fieldExpression = e => e.MyProperty;
Expression<Func<string, bool>> operatorExpression = e => e.Contains("irs");
// combine the two expressions somehow...
Expression<Func<MyEntity, bool>> combinedExpression = ???;
Assert.AreEqual(1, entities.Where(combinedExpression).Count());
}
Any suggestions as to how I might do this?
Btw the provider that will be resolving the expression is Linq for NHibernate.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
看一下您的两个表达式树:
您需要创建一个如下所示的新树:
您可以轻松地看到新树的哪些部分来自哪棵原始树。
要创建树,您需要使用第二个 lambda 表达式 (Call) 的主体,并将所有出现的
y
替换为第一个 lambda 表达式 (Property) 的主体以及所有出现的x< /code> 与
z
。然后,将结果包装在带有参数z
的新 lambda 表达式中。您可以使用 ExpressionVisitor 类 重写树,以及用于创建新的 lambda 表达式。
Take a look at your two expression trees:
You need to create a new tree that looks like this:
You can easily see what parts of the new tree come from which original tree.
To create the tree, you take the body of the second lambda expression (Call) and replace all occurrences of
y
with the body of the first lambda expression (Property) and all occurrences ofx
withz
. Then you wrap the result in a new lambda expression with parameterz
.You can use the ExpressionVisitor Class to rewrite the tree, and the Expression.Lambda Method to create the new lambda expression.
这取决于提供商支持什么;如果它支持子表达式(LINQ-to-SQL 支持,EF 不支持;我不知道 NH),那么:
但是,如果不支持,则需要使用
ExpressionVisitor
合并它们。It depends on what the provider supports; if it supports sub-expressions (LINQ-to-SQL does, EF doesn't; I don't know about NH), then:
however, if it doesn't you'll need to use
ExpressionVisitor
to merge them.按照 dtb 和 Marc 的建议,我使用 ExpressionVisitor 重写表达式树,这是我可以管理的最干净的:
并在我的单元测试中使用它:
Following the suggestion from dtb and Marc that I use the ExpressionVisitor to rewrite the expression tree, this was the cleanest I could manage:
And using it in my unit test:
尚未完成,这里是一个可以使用 2, 3, n 个表达式的版本
}
Out of completion, here is a version ready to work with 2, 3, n expressions
}