Создайте полностью динамичный, где пункт с деревом выражений и выполняется на IQueryable

В точке (3) в моем коде я определил запрос, названный query1, в котором я определил.Where лямбда-выражение. Этот запрос является в некотором роде динамичным, но все еще содержит статические элементы, он всегда относится к Сотруднику Типа и его (международному) свойству ClientID.

Теперь мне очень нравится делать обращение к типу и его свойству динамичным, на основе параметров метода, которые примером показывают ниже точки (1).

Что я пытался, до сих пор делает статическую часть запроса определенной под точкой (3) полностью динамичный путем замены его более тщательно продуманным деревом выражений, как записано в (4), (5) и (6). Но когда я пытаюсь добавить все вместе, что это говорит, что я называю.Where с неправильными параметрами. Я не знаю, как назвать.Where с правильными параметрами для создания полностью динамического выбора.

Кто-то знает для решения этой проблемы? Я провел день, ища и не нашел решение до сих пор.

        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;

Большое спасибо за чтение моего вопроса! Если у Вас есть вопросы о моем вопросе, спросите их:)

7
задан Wouter Vegter 9 August 2010 в 21:45
поделиться

1 ответ

Это довольно сложно рассматривать изолированно, но первое, что приходит на ум, это то, что Compile выглядит неуместным для IQueryable - это будет редко работают (за исключением LINQ-to-Objects).

Эквивалент WhereClause.Invoke (C.ClientID) - использовать Expression.Invoke для вызова подвыражения, но даже это ненадежно: LINQ-to-SQL будет поддерживать его, EF (по крайней мере, в 3.5) нет (возможно, «не»; я не перепроверил в 4.0). В конечном счете, было бы более надежно создать lambda1 как Expression > , если это возможно:

    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);

Затем передайте this в Где :

var query1 = employees.Where(lambda1);
20
ответ дан 6 December 2019 в 09:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: