Как я могу вычислить параметр выражения во время выполнения? - PullRequest
0 голосов
/ 17 мая 2018

Проблема, которую мне нужно решить, состоит в том, чтобы пропустить данные через операторы IF. Операторы IF генерируются таблицей SQL во время выполнения.

Мне удалось сделать это с помощью выражений и лямбда-выражений.

Моя таблица имеет memberName; Оператор; Target. Так, например, я получаю «Age», «GreaterThan» и «40» из таблицы и компилирую их.

    var rule = new Rule(rowRule["memberName"].ToString(), rowRule["Operator"].ToString(), rowRule["Target"].ToString());

                Func<User, bool> compiledRule = CompileRule<User>(rule);  

Я получаю истинное или ложное значение, и оно отлично работает.

     public static Func<T, bool> CompileRule<T>(Rule r)
    {
        var paramUser = Expression.Parameter(typeof(User));
        Expression expr = BuildExpr<T>(r, paramUser);
        // build a lambda function User->bool and compile it
        return Expression.Lambda<Func<T, bool>>(expr, paramUser).Compile();
    }

     static Expression BuildExpr<T>(Rule r, ParameterExpression param)
    {
        var left = MemberExpression.Property(param, r.MemberName);
        var tProp = typeof(T).GetProperty(r.MemberName).PropertyType;
        ExpressionType tBinary;
        // is the operator a known .NET operator?
        if (ExpressionType.TryParse(r.Operator, out tBinary))
        {
            var right = Expression.Constant(Convert.ChangeType(r.TargetValue, tProp));
            // use a binary operation, e.g. 'Equal' -> 'u.Age == 15'
            return Expression.MakeBinary(tBinary, left, right);
        }
        else
        {
            var method = tProp.GetMethod(r.Operator);
            var tParam = method.GetParameters()[0].ParameterType;
            var right = Expression.Constant(Convert.ChangeType(r.TargetValue, tParam));
            // use a method call, e.g. 'Contains' -> 'u.Tags.Contains(some_tag)'
            return Expression.Call(left, method, right);
        }
    }

Это прекрасно работает для простых операторов типа "Возраст> 30"

Но теперь мне нужно сделать его более сложным, вложив вычисления в операторы if, например, мне нужно обрабатывать операторы типа «Age> (30/2)»

Кто-нибудь знает, как я могу адаптировать свой механизм правил для выполнения вычислений.

Если я могу разобрать целевое значение, которое я получаю из таблицы, в код и выполнить его в методе, вернуть единственное значение, а затем создать правило, но я не уверен, как получить строку во время выполнения, разобрать в код и выполнить его.

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

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

...