コード例 #1
0
        Expression BuildExpr <T>(Rule r, ParameterExpression param)
        {
            Expression propExpression = null;
            Type       propType       = null;

            ExpressionType tBinary;

            if (string.IsNullOrEmpty(r.MemberName))//check is against the object itself
            {
                propExpression = param;
                propType       = propExpression.Type;
            }
            else if (r.MemberName.Contains('.'))//Child property
            {
                String[] childProperties = r.MemberName.Split('.');
                var      property        = typeof(T).GetProperty(childProperties[0]);
                var      paramExp        = Expression.Parameter(typeof(T), "SomeObject");

                propExpression = Expression.PropertyOrField(param, childProperties[0]);
                for (int i = 1; i < childProperties.Length; i++)
                {
                    var orig = property;
                    property = property.PropertyType.GetProperty(childProperties[i]);
                    if (property != null)
                    {
                        propExpression = Expression.PropertyOrField(propExpression, childProperties[i]);
                    }
                }
                propType = propExpression.Type;
            }
            else//Property
            {
                propExpression = Expression.PropertyOrField(param, r.MemberName);
                propType       = propExpression.Type;
            }

            // is the operator a known .NET operator?
            if (ExpressionType.TryParse(r.Operator, out tBinary))
            {
                var right = this.StringToExpression(r.TargetValue, propType);
                return(Expression.MakeBinary(tBinary, propExpression, right));
            }
            else if (r.Operator == "IsMatch")
            {
                return(Expression.Call(
                           typeof(Regex).GetMethod("IsMatch",
                                                   new[] { typeof(string), typeof(string), typeof(RegexOptions) }),
                           propExpression,
                           Expression.Constant(r.TargetValue, typeof(string)),
                           Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions))
                           ));
            }
            else //Invoke a method on the Property
            {
                var inputs     = r.Inputs.Select(x => x.GetType()).ToArray();
                var methodInfo = propType.GetMethod(r.Operator, inputs);
                if (!methodInfo.IsGenericMethod)
                {
                    inputs = null;//Only pass in type information to a Generic Method
                }
                var expressions = r.Inputs.Select(x => Expression.Constant(x)).ToArray();
                return(Expression.Call(propExpression, r.Operator, inputs, expressions));
            }
        }
コード例 #2
0
ファイル: MRE.cs プロジェクト: yesuvadian/MicroRuleEngine
 public static Func <T, bool> ToFunc <T>(Rule r, bool useTryCatchForNulls = true)
 {
     return(ToExpression <T>(r, useTryCatchForNulls).Compile());
 }
コード例 #3
0
ファイル: MRE.cs プロジェクト: yesuvadian/MicroRuleEngine
        private static Expression BuildExpr(Type type, Rule rule, Expression param, bool useTryCatch = true)
        {
            Expression propExpression;
            Type       propType;

            if (param.Type == typeof(object))
            {
                param = Expression.TypeAs(param, type);
            }
            var drule = rule as DataRule;

            if (string.IsNullOrEmpty(rule.MemberName)) //check is against the object itself
            {
                propExpression = param;
                propType       = propExpression.Type;
            }
            else if (drule != null)
            {
                if (type != typeof(System.Data.DataRow))
                {
                    throw new RulesException(" Bad rule");
                }
                propExpression = GetDataRowField(param, drule.MemberName, drule.Type);
                propType       = propExpression.Type;
            }
            else if (param.Type == typeof(XmlDocument) || param.Type.GetProperties().Count() == 0)
            {
                var expObjt = ExpressionFactory.GetExpressionObject(param.Type.ToString());
                propExpression = expObjt.GetExpression(param, rule);
                propType       = propExpression.Type;
            }

            else
            {
                propExpression = GetProperty(param, rule.MemberName);
                propType       = propExpression.Type;
            }
            if (useTryCatch)
            {
                propExpression = Expression.TryCatch(
                    Expression.Block(propExpression.Type, propExpression),
                    Expression.Catch(typeof(NullReferenceException), Expression.Default(propExpression.Type))
                    );
            }

            // is the operator a known .NET operator?
            ExpressionType tBinary;

            if (ExpressionType.TryParse(rule.Operator, out tBinary))
            {
                Expression right;
                var        txt = rule.TargetValue as string;
                if (txt != null && txt.StartsWith("*."))
                {
                    txt   = txt.Substring(2);
                    right = GetProperty(param, txt);
                }
                else
                {
                    right = StringToExpression(rule.TargetValue, propType);
                }

                return(Expression.MakeBinary(tBinary, propExpression, right));
            }

            switch (rule.Operator)
            {
            case "IsMatch":
            {
                var exprObj = ExpressionFactory.GetExpressionObject(param.Type.ToString());
                if (exprObj != null)
                {
                    Expression expMember = exprObj.GetExpression(param, rule);
                }

                return(Expression.Call(
                           _miRegexIsMatch.Value,
                           propExpression,
                           Expression.Constant(rule.TargetValue, typeof(string)),
                           Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions))
                           ));
            }

            case "IsInteger":
                return(Expression.Call(
                           _miIntTryParse.Value,
                           propExpression,
                           Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Int"))
                           ));

            case "IsSingle":
                return(Expression.Call(
                           _miFloatTryParse.Value,
                           propExpression,
                           Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Float"))
                           ));

            case "IsDouble":
                return(Expression.Call(
                           _miDoubleTryParse.Value,
                           propExpression,
                           Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Double"))
                           ));

            case "IsDecimal":
                return(Expression.Call(
                           _miDecimalTryParse.Value,
                           propExpression,
                           Expression.MakeMemberAccess(null, typeof(Placeholder).GetField("Decimal"))
                           ));

            default:
                break;
            }

            var enumrOperation = IsEnumerableOperator(rule.Operator);

            if (enumrOperation != null)
            {
                var elementType = ElementType(propType);
                var lambdaParam = Expression.Parameter(elementType, "lambdaParam");
                return(rule.Rules?.Any() == true
                    ? Expression.Call(enumrOperation.MakeGenericMethod(elementType),
                                      propExpression,
                                      Expression.Lambda(
                                          BuildNestedExpression(elementType, rule.Rules, lambdaParam, ExpressionType.AndAlso),
                                          lambdaParam)


                                      )
                    : Expression.Call(enumrOperation.MakeGenericMethod(elementType), propExpression));
            }
            else //Invoke a method on the Property
            {
                var inputs     = rule.Inputs.Select(x => x.GetType()).ToArray();
                var methodInfo = propType.GetMethod(rule.Operator, inputs);
                List <Expression> expressions = new List <Expression>();

                if (methodInfo == null)
                {
                    methodInfo = propType.GetMethod(rule.Operator);
                    if (methodInfo != null)
                    {
                        var parameters = methodInfo.GetParameters();
                        int i          = 0;
                        foreach (var item in rule.Inputs)
                        {
                            expressions.Add(MRE.StringToExpression(item, parameters[i].ParameterType));
                            i++;
                        }
                    }
                }
                else
                {
                    expressions.AddRange(rule.Inputs.Select(Expression.Constant));
                }
                if (methodInfo == null)
                {
                    throw new RulesException($"'{rule.Operator}' is not a method of '{propType.Name}");
                }


                if (!methodInfo.IsGenericMethod)
                {
                    inputs = null; //Only pass in type information to a Generic Method
                }
                var callExpression = Expression.Call(propExpression, rule.Operator, inputs, expressions.ToArray());
                if (useTryCatch)
                {
                    return(Expression.TryCatch(
                               Expression.Block(typeof(bool), callExpression),
                               Expression.Catch(typeof(NullReferenceException), Expression.Constant(false))
                               ));
                }
                else
                {
                    return(callExpression);
                }
            }
        }
コード例 #4
0
ファイル: MRE.cs プロジェクト: yesuvadian/MicroRuleEngine
 public static Func <object, bool> ToFunc(Type type, Rule r)
 {
     return(ToExpression(type, r).Compile());
 }
コード例 #5
0
ファイル: MRE.cs プロジェクト: ansark/Rule-Engine
        Expression BuildExpr <T>(Rule r, ParameterExpression OrderType)
        {
            Expression propertyOnOrder = null;
            Type       propType        = null;

            ExpressionType tBinary;

            if (string.IsNullOrEmpty(r.MemberName))//check is against the object itself
            {
                propertyOnOrder = OrderType;
                propType        = propertyOnOrder.Type;
            }
            else if (r.MemberName.Contains('.'))//Child property
            {
                String[] childProperties = r.MemberName.Split('.');
                var      property        = typeof(T).GetProperty(childProperties[0]);
                var      paramExp        = Expression.Parameter(typeof(T), "SomeObject");

                propertyOnOrder = Expression.PropertyOrField(OrderType, childProperties[0]);
                for (int i = 1; i < childProperties.Length; i++)
                {
                    var orig = property;
                    property = property.PropertyType.GetProperty(childProperties[i]);
                    if (property != null)
                    {
                        propertyOnOrder = Expression.PropertyOrField(propertyOnOrder, childProperties[i]);
                    }
                }
                propType = propertyOnOrder.Type;
            }
            else//Property
            {
                propertyOnOrder = Expression.PropertyOrField(OrderType, r.MemberName);
                propType        = propertyOnOrder.Type;
            }

            // is the operator a known .NET operator?
            if (ExpressionType.TryParse(r.Operator, out tBinary) || r.Operator == "Function")
            {
                //no repetition of error message,action or setter found
                Expression           right        = null;
                BinaryExpression     binary       = null;
                MethodCallExpression ErrorMessage = Expression.Call(OrderType, "AddMessage", null, new Expression[] { Expression.Constant(r.ErrorMessage) });
                if (r.Operator != "Function")
                {
                    right  = this.StringToExpression(r.TargetValue, propType);
                    binary = Expression.MakeBinary(tBinary, propertyOnOrder, right);
                }
                //function
                if (!string.IsNullOrEmpty(r.Function))
                {
                    // var firstexp = Expression.MakeBinary(tBinary, propertyOnOrder, right);
                    Expression[] functionParams = new Expression[] { Expression.Constant(r.ErrorMessage) };

                    Expression FunctionCall = Expression.Call(OrderType, r.Function, null, r.Inputs.Select(x => Expression.Constant(x)).ToArray());

                    if (r.Operator == "Function")
                    {
                        //call functon and if the function returns false, set error message

                        //Expression.IfThenElse(FunctionCall, Expression.Constant(true)


                        return(Expression.Condition(FunctionCall, Expression.Constant(true),
                                                    Expression.Block(ErrorMessage, Expression.Condition(Expression.Constant(r.ReturnTue),
                                                                                                        Expression.Constant(true), Expression.Constant(true)))));
                    }
                    return(Expression.Block(Expression.IfThenElse(binary, FunctionCall, ErrorMessage),
                                            Expression.Condition(Expression.Constant(r.ReturnTue), Expression.Condition(binary, binary, Expression.Not(binary)), binary)
                                            ));//need fix-u dont
                    //
                }
                //setter
                else if (!string.IsNullOrEmpty(r.Setter))
                {
                    //no repetition of error message,action or setter found
                    var prop1 = Expression.PropertyOrField(OrderType, r.Setter.Split('=')[0]);
                    var prop2 = Expression.Constant(r.Setter.Split('=')[1]);
                    return(Expression.Block(Expression.IfThenElse(binary, Expression.Assign(prop1, prop2), ErrorMessage),
                                            Expression.Condition(Expression.Constant(r.ReturnTue), Expression.Condition(binary, binary, Expression.Not(binary)), binary)
                                            ));
                    //
                }
                //
                else
                {
                    return(Expression.Block(Expression.IfThen(Expression.Not(binary), ErrorMessage),
                                            Expression.Condition(Expression.Constant(r.ReturnTue), Expression.Condition(binary, binary, Expression.Not(binary)), binary)
                                            ));
                    //var ifthen = Expression.IfThen(Expression.Not(binary), ErrorMessage);
                    //return Expression.Block(ifthen, binary);
                }
            }
            else if (r.Operator == "IsMatch")
            {
                var tester = Expression.Call(
                    typeof(Regex).GetMethod("IsMatch",
                                            new[] { typeof(string), typeof(string), typeof(RegexOptions) }),
                    propertyOnOrder,
                    Expression.Constant(r.TargetValue, typeof(string)),
                    Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions))
                    );

                return(Expression.Block(Expression.IfThen(tester,
                                                          Expression.Call(OrderType, "AddMessage", null, new Expression[] { Expression.Constant(r.MemberName) })), tester));
            }
            else //Invoke a method on the Property
            {
                Type[] parameterTypes = r.Inputs.Select(x => x.GetType()).ToArray();
                var    methodInfo     = propType.GetMethod(r.Operator, parameterTypes);
                if (!methodInfo.IsGenericMethod)
                {
                    parameterTypes = null;//Only pass in type information to a Generic Method
                }
                Expression[] prametersAsArray = r.Inputs.Select(x => Expression.Constant(x)).ToArray();
                var          firstcall        = Expression.Call(propertyOnOrder, r.Operator, parameterTypes, prametersAsArray);

                var message = Expression.Call(OrderType, "AddMessage", null, new Expression[] { Expression.Constant(r.MemberName) });
                var ifthen  = Expression.IfThen(Expression.Not(firstcall), message);
                return(Expression.Block(ifthen, firstcall));
            }
        }
コード例 #6
0
        private static Expression BuildExpr(Type type, Rule r, Expression param)
        {
            Expression propExpression;
            Type       propType;

            if (param.Type == typeof(object))
            {
                param = Expression.TypeAs(param, type);
            }
            var drule = r as DataRule;

            if (string.IsNullOrEmpty(r.MemberName)) //check is against the object itself
            {
                propExpression = param;
                propType       = propExpression.Type;
            }
            else if (drule != null)
            {
                if (type != typeof(System.Data.DataRow))
                {
                    throw new RulesException(" Bad rule");
                }
                propExpression = GetDataRowField(param, drule.MemberName, drule.Type);
                propType       = propExpression.Type;
            }
            else
            {
                propExpression = GetProperty(param, r.MemberName);
                propType       = propExpression.Type;
            }

            propExpression = Expression.TryCatch(
                Expression.Block(propExpression.Type, propExpression),
                Expression.Catch(typeof(NullReferenceException), Expression.Default(propExpression.Type))
                );
            // is the operator a known .NET operator?
            ExpressionType tBinary;

            if (Enum.TryParse(r.Operator, out tBinary))
            {
                var right = StringToExpression(r.TargetValue, propType);
                return(Expression.MakeBinary(tBinary, propExpression, right));
            }
            if (r.Operator == "IsMatch")
            {
                return(Expression.Call(
                           _miRegexIsMatch.Value,
                           propExpression,
                           Expression.Constant(r.TargetValue, typeof(string)),
                           Expression.Constant(RegexOptions.IgnoreCase, typeof(RegexOptions))
                           ));
            }
            else //Invoke a method on the Property
            {
                var inputs  = r.Inputs.Select(x => x.GetType()).ToArray();
                var methods = propType.GetMethods();

                var methodInfo = propType.GetMethod(r.Operator, inputs);
                if (!methodInfo.IsGenericMethod)
                {
                    inputs = null;//Only pass in type information to a Generic Method
                }
                var expressions = r.Inputs.Select(Expression.Constant).ToArray();

                return(Expression.TryCatch(
                           Expression.Block(typeof(bool), Expression.Call(propExpression, r.Operator, inputs, expressions)),
                           Expression.Catch(typeof(NullReferenceException), Expression.Constant(false))
                           ));
            }
        }