Использование LINQ ExpressionVisitor для замены параметров примитива ссылками на свойства в лямбда-выражении

Я нахожусь в процессе написания слоя данных для части нашей системы, которая регистрирует информацию об автоматизированных заданиях, которые выполняются каждый день - название задания, как долго оно выполнялось, каков был результат и т. Д.

Я разговариваю с базой данных с использованием Entity Framework, но я пытаюсь скрыть эти детали от модулей более высокого уровня и не хочу, чтобы сами объекты сущности были открыты.

Тем не менее, я хотел бы сделать мой интерфейс очень гибким по критериям, которые он использует для поиска информации о работе. Например, пользовательский интерфейс должен позволять пользователю выполнять сложные запросы, такие как "дать мне все задания с именем" привет ". который проходил с 10:00 до 11:00, что не удалось. & quot; Очевидно, это выглядит как работа для динамическиExpression деревья.

Поэтому мне хотелось бы, чтобы мой уровень данных (хранилище) мог принимать выражения типа LINQExpression<Func<string, DateTime, ResultCode, long, bool>> (лямбда-выражение), а затем за кулисами преобразовать эту лямбда-выражение в выражение, которое моя Entity FrameworkObjectContext можно использовать в качестве фильтра внутриWhere() пункт.

Короче говоря, я пытаюсь преобразовать лямбда-выражение типаExpression<Func<string, DateTime, ResultCode, long, bool>> вExpression<Func<svc_JobAudit, bool>>, гдеsvc_JobAudit является объектом данных Entity Framework, который соответствует таблице, в которой хранится информация о задании. (Четыре параметра в первом делегате соответствуют названию задания, времени его выполнения, результату и времени выполнения в MS соответственно)

Я делал очень хорошие успехи, используяExpressionVisitor класс, пока я не ударил кирпичную стену и не получилInvalidOperationException с этим сообщением об ошибке:

When called from 'VisitLambda', rewriting a node of type 'System.Linq.Expressions.ParameterExpression' must return a non-null value of the same type. Alternatively, override 'VisitLambda' and change it to not visit children of this type.

Я полностью сбит с толку. Почему, черт возьми, это не позволяет мне преобразовывать узлы выражения, которые ссылаются на параметры, в узлы, которые ссылаются на свойства? Есть ли другой способ пойти по этому поводу?

Вот пример кода:

namespace ExpressionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<string, DateTime, ResultCode, long, bool>> expression = (myString, myDateTime, myResultCode, myTimeSpan) => myResultCode == ResultCode.Failed && myString == "hello";
            var result = ConvertExpression(expression);
        }

        private static Expression<Func<svc_JobAudit, bool>> ConvertExpression(Expression<Func<string, DateTime, ResultCode, long, bool>> expression)
        {
            var newExpression = Expression.Lambda<Func<svc_JobAudit, bool>>(new ReplaceVisitor().Modify(expression), Expression.Parameter(typeof(svc_JobAudit)));
            return newExpression;
        }
    }

    class ReplaceVisitor : ExpressionVisitor
    {
        public Expression Modify(Expression expression)
        {
            return Visit(expression);
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            if (node.Type == typeof(string))
            {
                return Expression.Property(Expression.Parameter(typeof(svc_JobAudit)), "JobName");
            }
            return node;
        }
    }
}

Ответы на вопрос(2)

Ваш ответ на вопрос