コード例 #1
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);
                }
            }
        }
コード例 #2
0
        static void Main(string[] args)
        {
            //only first message will be displayed.
            //sample code to display all messages added
            //setter will set a value to a property if the specified condition is satisfied, In setter,return true can be used if u want it to return true even if its false
            //
            //objectives
            //1.All setter and actions should be executed exactly once. "False event" should be raised once and once only-seems correct now
            //2. add "return true" functionality without causing the expression to be executed twice-done
            //3.Provide UI to serialize a class and test it.
            //4.Provide XML & Json serilization option
            //5. add more functionality

            Appointment app1 = new Appointment();

            app1.Flow            = "Import";
            app1.BE              = "asd";
            app1.ContainerNumber = string.Empty;
            Rule ruleCreateRequest = new Rule()
            {
                Operator = "AndAlso",
                Rules    = new List <Rule>()
                {
                    new Rule()
                    {
                        Operator = "Function", Function = "CheckLength", ErrorMessage = "Incorrect length"
                    },
                    new Rule {
                        Operator = "Function", Function = "AppointMentMaxDays", ErrorMessage = "Appointment is not in the allowed window of date"
                    },
                    new Rule
                    {
                        Operator = "OrElse",
                        Rules    = new List <Rule>()
                        {
                            new Rule()
                            {
                                Operator = "AndAlso",
                                Rules    = new List <Rule>
                                {
                                    new Rule {
                                        MemberName = "Flow", TargetValue = "Import", Operator = "Equal"
                                    },
                                    new Rule
                                    {
                                        Operator = "AndAlso",
                                        Rules    = new List <Rule>
                                        {
                                            new Rule
                                            {
                                                Operator = "OrElse",
                                                Rules    = new List <Rule>()
                                                {
                                                    new Rule {
                                                        MemberName = "ContainerNumber", TargetValue = null, Operator = "NotEqual", ErrorMessage = "Container number is null"
                                                    },
                                                    new Rule {
                                                        MemberName = "BE", TargetValue = null, Operator = "NotEqual", ErrorMessage = "BE number is null"
                                                    }
                                                }
                                            },
                                            new Rule
                                            {
                                                Operator = "OrElse",
                                                Rules    = new List <Rule>()
                                                {
                                                    new Rule {
                                                        MemberName = "ContainerNumber", TargetValue = string.Empty, Operator = "NotEqual", ErrorMessage = "Container number is empty"
                                                    },
                                                    new Rule {
                                                        MemberName = "BE", TargetValue = string.Empty, Operator = "NotEqual", ErrorMessage = "BE number is empty"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                            new Rule()
                            {
                                Operator = "AndAlso",
                                Rules    = new List <Rule>
                                {
                                    new Rule {
                                        MemberName = "Flow", TargetValue = "Export", Operator = "Equal"
                                    },
                                    new Rule
                                    {
                                        Operator = "AndAlso",
                                        Rules    = new List <Rule>
                                        {
                                            new Rule
                                            {
                                                Operator = "OrElse",
                                                Rules    = new List <Rule>()
                                                {
                                                    new Rule {
                                                        MemberName = "ContainerNumber", TargetValue = null, Operator = "NotEqual", ErrorMessage = "Container number is null"
                                                    },
                                                    new Rule {
                                                        MemberName = "BookingNumber", TargetValue = null, Operator = "NotEqual", ErrorMessage = "Booking number is null"
                                                    }
                                                }
                                            },
                                            new Rule
                                            {
                                                Operator = "OrElse",
                                                Rules    = new List <Rule>()
                                                {
                                                    new Rule {
                                                        MemberName = "ContainerNumber", TargetValue = string.Empty, Operator = "NotEqual", ErrorMessage = "Container number is empty"
                                                    },
                                                    new Rule {
                                                        MemberName = "BookingNumber", TargetValue = string.Empty, Operator = "NotEqual", ErrorMessage = "Booking number is empty"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                            new Rule()
                            {
                                Operator = "AndAlso",
                                Rules    = new List <Rule>
                                {
                                    new Rule {
                                        MemberName = "Flow", TargetValue = "Special", Operator = "Equal"
                                    },
                                    new Rule
                                    {
                                        Operator = "AndAlso",
                                        Rules    = new List <Rule>
                                        {
                                            new Rule
                                            {
                                                Operator = "OrElse",
                                                Rules    = new List <Rule>()
                                                {
                                                    new Rule {
                                                        MemberName = "ContainerNumber", TargetValue = null, Operator = "NotEqual", ErrorMessage = "3. Container number is null"
                                                    },
                                                    new Rule {
                                                        MemberName = "BookingNumber", TargetValue = null, Operator = "NotEqual", ErrorMessage = "3.Booking number is null"
                                                    }
                                                }
                                            },
                                            new Rule
                                            {
                                                Operator = "OrElse",
                                                Rules    = new List <Rule>()
                                                {
                                                    new Rule {
                                                        MemberName = "ContainerNumber", TargetValue = string.Empty, Operator = "NotEqual", ErrorMessage = "3.Container number is empty"
                                                    },
                                                    new Rule {
                                                        MemberName = "BookingNumber", TargetValue = string.Empty, Operator = "NotEqual", ErrorMessage = "3.Booking number is empty"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                        }
                    }
                }
            };
            Rule newRule = new Rule()
            {
                Operator = "AndAlso",
                Rules    = new List <Rule>()
                {
                    new Rule()
                    {
                        MemberName = "Flow", Operator = "Equal", TargetValue = "Import", Function = "SetCharges", Inputs = new List <object> {
                            "34.5"
                        }, ErrorMessage = "Incorrect flow", ReturnTue = true
                    },
                    new Rule {
                        MemberName = "ContainerNumber", TargetValue = "", Operator = "NotEqual", Setter = "ContainerNumber=CONT123", ErrorMessage = "Container number not provided", ReturnTue = true
                    },
                    new Rule {
                        MemberName = "BE", TargetValue = "", Operator = "NotEqual", ErrorMessage = "BE number is not provided", ReturnTue = true
                    }
                }
            };

            MRE m           = new MRE();
            var newfunction = m.CompileRule <Appointment>(ruleCreateRequest);
            var status      = newfunction(app1);



            Rule ruleSendAppointment = new Rule()
            {
                Operator = "AndAlso",
                Rules    = new List <Rule>()
                {
                    new Rule()
                    {
                        MemberName = "Date", TargetValue = "12-jan-2019", Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "TimeSlotFrom", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "TimeSlotTo", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "AlreadyBooked", TargetValue = "true", Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        Operator = "OrElse",
                        Rules    = new List <Rule>()
                        {
                            new Rule
                            {
                                Operator = "AndAlso",
                                Rules    = new List <Rule>()
                                {
                                    new Rule {
                                        MemberName = "TransactionType", TargetValue = "DI", Operator = "Equal"
                                    },
                                    new Rule {
                                        MemberName = "Flow", TargetValue = "Import", Operator = "Equal"
                                    },
                                    new Rule {
                                        MemberName = "IDO", TargetValue = null, Operator = "NotEqual"
                                    },
                                    new Rule {
                                        MemberName = "IDO", TargetValue = string.Empty, Operator = "NotEqual"
                                    }
                                }
                            },
                            new Rule
                            {
                                Operator = "OrElse",
                                Rules    = new List <Rule>()
                                {
                                    new Rule {
                                        MemberName = "TransactionType", TargetValue = "DI", Operator = "NotEqual"
                                    },
                                    new Rule {
                                        MemberName = "Flow", TargetValue = "Import", Operator = "NotEqual"
                                    }
                                }
                            }
                        }
                    }
                }
            };
            Rule ruleCharges = new Rule
            {
                Operator = "AndAlso",
                Rules    = new List <Rule>()
                {
                    new Rule()
                    {
                        MemberName = "Date", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "TimeSlotFrom", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "TimeSlotTo", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "TruckType", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "TruckType", TargetValue = string.Empty, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "DriverContact", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "DriverContact", TargetValue = string.Empty, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "DriverName", TargetValue = string.Empty, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "DriverName", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "NotificationType", TargetValue = string.Empty, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "NotificationType", TargetValue = null, Operator = "NotEqual"
                    },
                    new Rule()
                    {
                        MemberName = "AlreadyBooked", TargetValue = "No", Operator = "Equal"
                    }
                }
            };

            app1 = new Appointment();

            app1.Flow            = "Import";
            app1.BE              = string.Empty;
            app1.ContainerNumber = string.Empty;

            m           = new MRE();
            newfunction = m.CompileRule <Appointment>(ruleSendAppointment);
            status      = newfunction(app1);
            //compileRule<Appointment>(ruleCreateRequest, app1);


            //Console.WriteLine(status.ToString().ToUpper());
            //Console.WriteLine("---------------------------");

            foreach (var item in app1.messages)
            {
                Console.WriteLine(item);
            }
            //Console.WriteLine("---------------------------");
            //foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(app1))
            //{
            //    string name = descriptor.Name;
            //    object value = descriptor.GetValue(app1);
            //    Console.WriteLine("{0}={1}", name, value);
            //}

            Console.Read();
        }