コード例 #1
0
        /// <summary>
        /// Parse the expression tree
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="parm"></param>
        /// <returns></returns>
        private static Expression ParseTree <T>(
            ConditionRuleSet condition,
            ParameterExpression parm)
        {
            IEnumerable <ConditionRuleSet> rules = condition.Rules;

            Binder binder = condition.Separator == ConditionRuleSeparator.Or ? (Binder)Expression.Or : Expression.And;

            Expression bind(Expression lef, Expression right) => lef == null ? right : binder(lef, right);

            Expression left = null;

            // If multiple rules inner
            if (condition.Rules != null && condition.Rules.Any())
            {
                foreach (var rule in condition.Rules)
                {
                    left = bind(left, CreateRuleExpression <T>(rule, parm));
                }
            }
            else
            {
                left = bind(left, CreateRuleExpression <T>(condition, parm));
            }

            return(left);
        }
コード例 #2
0
        private static Expression GetExpression(ConditionRuleSet rule, ParameterExpression param, string field, object value)
        {
            MemberExpression property = null;

            foreach (var member in field.Split('.'))
            {
                if (property == null)
                {
                    property = Expression.Property(param, member);
                }
                else
                {
                    property = Expression.Property(property, member);
                }
            }

            return(CreateOperationExpression(property, rule.Operator, value));
        }
コード例 #3
0
        private static MethodCallExpression HandleTableRule(ConditionRuleSet rule, string field, object value, MemberExpression property)
        {
            // Get the type of T in the IEnumerable<T> or ICollection<T> list
            var childType = property.Type.GetGenericArguments().First();

            // Set it as the param of the any expression
            var param         = Expression.Parameter(childType);
            var anyExpression = Expression.Lambda(GetExpression(rule, param, field, value), param);


            var anyMethod = typeof(Enumerable).GetMethods().Single(m => m.Name == "Any" && m.GetParameters().Length == 2);

            anyMethod = anyMethod.MakeGenericMethod(childType);

            var predicate = Expression.Call(anyMethod, property, anyExpression);

            return(predicate);
        }
コード例 #4
0
        /// <summary>
        /// Transform the ConditionRuleSet object to an expression function
        /// that can be evaluated in LinqToSql queries or whatever
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="rules"></param>
        /// <returns></returns>
        public static Expression <Func <T, bool> > ParseExpression <T>(ConditionRuleSet rules)
        {
            var itemExpression = Expression.Parameter(typeof(T));
            var conditions     = ParseTree <T>(rules, itemExpression);

            // If no conditions parsed
            // Let's return a true predicate
            if (conditions == null)
            {
                return((m) => true);
            }

            if (conditions.CanReduce)
            {
                conditions = conditions.ReduceAndCheck();
            }

            Console.WriteLine(conditions.ToString());

            var query = Expression.Lambda <Func <T, bool> >(conditions, itemExpression);

            return(query);
        }
コード例 #5
0
        private static ValidateExpressionResult ValidateExpressionRecursive(ConditionRuleSet rule, IEnumerable <string> fieldWhiteList)
        {
            if (!string.IsNullOrEmpty(rule.Field) && !fieldWhiteList.Contains(rule.Field))
            {
                return(new ValidateExpressionResult()
                {
                    InvalidField = rule.Field
                });
            }

            if (rule.Rules != null)
            {
                foreach (var subRule in rule.Rules)
                {
                    var evaluate = ValidateExpressionRecursive(subRule, fieldWhiteList);
                    if (!evaluate.Success)
                    {
                        return(evaluate);
                    }
                }
            }

            return(ValidateExpressionResult.Valid);
        }
コード例 #6
0
        private static Expression CreateRuleExpression <T>(ConditionRuleSet rule, ParameterExpression parm)
        {
            Expression right = null;

            if (rule.Separator.HasValue && rule.Rules != null && rule.Rules.Any())
            {
                right = ParseTree <T>(rule, parm);
                return(right);
            }

            // If the field is empty, then return true
            if (string.IsNullOrEmpty(rule.Field))
            {
                return(right);
            }

            MemberExpression property = null;

            try
            {
                string field  = rule.Field;
                var    fields = field.Split('.');
                int    i      = 0;
                foreach (var member in fields)
                {
                    i = i + member.Length + 1;
                    if (property == null)
                    {
                        property = Expression.Property(parm, member);
                    }
                    else
                    {
                        property = Expression.Property(property, member);
                    }

                    if (property.Type.IsArray())
                    {
                        string subField = "";
                        try
                        {
                            subField = field.Substring(i, field.Length - i);
                            if (string.IsNullOrEmpty(subField))
                            {
                                throw new Exception("");
                            }
                        }
                        catch
                        {
                            throw new JsonRuleEngineException(JsonRuleEngineExceptionCategory.InvalidField, $"The array {field} does not have a subfield. e.g. {field}.Id");
                        }
                        right = HandleTableRule(rule, subField, rule.Value, property);
                        return(right);
                    }
                }
            }
            catch (Exception e)
            {
                throw new JsonRuleEngineException(JsonRuleEngineExceptionCategory.InvalidField, $"The provided field is invalid {rule.Field} : {e.Message} ");
            }

            return(CreateOperationExpression(property, rule.Operator, rule.Value));
        }
コード例 #7
0
        /// <summary>
        /// Test the conditions
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj">The object to test</param>
        /// <param name="rules">The conditionRuleSet object</param>
        /// <returns>True if the conditions are matched</returns>
        public static bool Evaluate <T>(T obj, ConditionRuleSet rules)
        {
            var query = ParseExpression <T>(rules);

            return(query.Compile().Invoke(obj));
        }