如何组合两个表达式?

Jon*_*att 5 c# linq linq-to-nhibernate

我正在尝试构建一个将应用于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());
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想分开表达式的两个部分:

[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());
}
Run Code Online (Sandbox Code Playgroud)

有关如何做到这一点的任何建议?

Btw将解析表达式的提供程序是Linq for NHibernate.

dtb*_*dtb 5

看看你的两个表达式树:

                 |                                      |
               Lambda                                Lambda
              /      \                              /      \
             /        \                            /        \
     Property          Parameter x               Call        Parameter y
    /        \                                  /  |  \
   /          \                                /   |   \
  x           MyProperty              EndsWidth    y    Constant
                                                        |
                                                       "5"

您需要创建一个如下所示的新树:

                                 |
                               Lambda
                              /      \
                             /        \
                           Call        Parameter z
                          /  |  \
                         /   |   \
                   EndsWith  |   Constant
                             |         \
                          Property     "5"
                         /        \
                        /          \
                       z          MyProperty

您可以轻松地看到新树的哪些部分来自哪个原始树.

要创建树,可以获取第二个lambda表达式(Call)y的主体,并将所有出现的内容替换为第一个lambda表达式(Property)的主体以及所有出现的xwith z.然后将结果包装在带有参数的新lambda表达式中z.

您可以使用ExpressionVisitor类重写树,使用Expression.Lambda方法创建新的lambda表达式.