首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用表达式树创建完全动态的where子句,并在IQueryable上执行

使用表达式树创建完全动态的where子句,并在IQueryable上执行
EN

Stack Overflow用户
提问于 2010-08-10 05:45:38
回答 1查看 10.5K关注 0票数 7

在代码中的第(3)点,我定义了一个名为query1的查询,其中我定义了一个.Whereλ表达式。这个查询在某种程度上是动态的,但仍然包含静态元素,它总是引用类型Employee及其(整型)属性ClientID。

现在,我非常喜欢基于方法参数来动态引用类型及其属性,这些方法参数通过示例显示在第(1)点下面。

到目前为止,我尝试的是使点(3)下定义的查询的静态部分完全动态,将其替换为(4)、(5)和(6)中所写的更精细的表达式树。但是,当我尝试将所有内容加在一起时,它会说我使用错误的参数调用.Where。我不知道如何使用正确的参数调用.Where来创建一个完全动态的select。

有人知道如何解决这个问题吗?我花了一天的时间寻找,到目前为止还没有找到解决方案。

代码语言:javascript
复制
        dsMain domainService = new dsMain();


        //(1)i want to rewrite the following four variables to method-parameters
        Type entityType = typeof(Employee);
        String targetProperty = "ClientID";
        Type entityProperty = typeof(Employee).GetProperty(targetProperty).PropertyType;
        int idToDelete = 5;


        //(2)create expression-function: idToDelete == entityType.targetProperty (in this case: Employee.ClientID)
        ParameterExpression numParam = Expression.Parameter(entityProperty, targetProperty.Substring(0, 3));
        ConstantExpression equalTarget = Expression.Constant(idToDelete, idToDelete.GetType());
        BinaryExpression intEqualsID = Expression.Equal(numParam, equalTarget);
        Expression<Func<int, bool>> lambda1 =
                    Expression.Lambda<Func<int, bool>>(
                    intEqualsID,
                    new ParameterExpression[] { numParam });

        //(3)I want to create query1 fully dynamic, so defining Employee or an other type and its property at run time
        WhereClause = lambda1.Compile();
        IQueryable<Employee> employees = domainService.GetEmployees();
        var query1 = employees.Where<Employee>(C => WhereClause.Invoke(C.ClientID)).Expression;



        //(4)create the operand body {value(ASP.test_aspx).WhereClause.Invoke(E.ClientID)}
        var operandbodyMethod = WhereClause.GetType().GetMethod("Invoke");
        var operandbodyType = typeof(System.Boolean);
        var operandbodyArgs1Expression = Expression.Parameter(entityType, entityType.Name.Substring(0, 1));
        var operandbodyArgs1 = Expression.MakeMemberAccess(operandbodyArgs1Expression, entityType.GetMember(targetProperty)[0]);
        var operandBodyObjectExp = Expression.Constant(this, this.GetType());
        var operandbodyObject = Expression.MakeMemberAccess(operandBodyObjectExp, this.GetType().GetMember("WhereClause")[0]);

        //(5)create the operand {E => value(ASP.test_aspx).WhereClause.Invoke(E.ClientID)}
        var operandbody = Expression.Call(operandbodyObject, operandbodyMethod, operandbodyArgs1);
        var operandParameter = Expression.Parameter(entityType, entityType.Name.Substring(0, 1));
        var operandType = typeof(Func<,>).MakeGenericType(entityType, typeof(System.Boolean));

        //(6)
        var operand = Expression.Lambda(operandType, operandbody, new ParameterExpression[] { operandParameter });
        var expressionType = typeof(Expression<>).MakeGenericType(operandType);
        var completeWhereExpression = Expression.MakeUnary(ExpressionType.Quote, operand, expressionType);


        //(7)the line below does not work
        var query2 = employees.Where<Employee>(completeWhereExpression).Expression;

非常感谢你阅读我的问题!如果您对我的问题有疑问,请问他们:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-08-10 13:41:48

这很难孤立地看待,但首先发生的是Compile看起来与IQueryable格格不入-这几乎不会工作(LINQ- to -Objects是个例外)。

WhereClause.Invoke(C.ClientID)的一个等价物是使用Expression.Invoke调用子表达式,但这也是一个缺陷: LINQ- to -SQL将支持它,EF (至少在3.5中)不支持它(可能“没有”;我还没有在4.0中重新签入)。最终,如果可能的话,将lambda1创建为Expression<Func<Employee,bool>>会更健壮:

代码语言:javascript
复制
    ParameterExpression empParam = Expression.Parameter(typeof(Employee),"emp");
    ConstantExpression equalTarget = Expression.Constant(idToDelete, idToDelete.GetType());
    BinaryExpression intEqualsID = Expression.Equal(
        Expression.PropertyOrField(empParam, targetProperty), equalTarget);
    Expression<Func<Exmployee, bool>> lambda1 =
                Expression.Lambda<Func<int, bool>>(
                intEqualsID,
                empParam);

然后将这个传递给Where

代码语言:javascript
复制
var query1 = employees.Where(lambda1);
票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3444457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档