0

我想使用运行时索引器而不是某些固定的零索引值来验证针对输入数组数据的规则。如果我在 session.Insert() 中一一插入数据,它就可以工作 如果我将 session.InsertAll() 与数组数据一起使用,它就不起作用

我尝试向索引器提供 Expression.Constant 值,但没有操作触发器

class Program
    {
        static void Main(string[] args)
        {
            RuleTestWithSingleInsertData();

           // RuleTestWithInsertDataAll();

            Console.ReadKey();
        }

        public static void RuleTestWithSingleInsertData()
        {
            try
            {
                CustomRuleRepository repository = new CustomRuleRepository();

                List<RuleEngineEntity> rules = new List<RuleEngineEntity>();
                rules.Add(new RuleEngineEntity { FieldName = "Age", Name = "CustomerCheck", Value = 25 });

                repository.LoadRuleForTest1(rules.FirstOrDefault());

                //Compile rules
                var factory = repository.Compile();

                //Create a working session
                var session = factory.CreateSession();

                RuleEngineRequestModel ruleEngineRequestModel = new RuleEngineRequestModel
                {
                    ruleList = rules,
                    customerData = new List<Customer>() { new Customer { Name = "A", Age = 19 },
                    new Customer { Name = "B", Age = 26 } }.ToArray()
                };

                 session.InsertAll(ruleEngineRequestModel.customerData);

                var IspassedorNot = session.Fire(); 
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        public static void RuleTestWithInsertDataAll()
        {
            try
            {
                CustomRuleRepository repository = new CustomRuleRepository();

                List<RuleEngineEntity> rules = new List<RuleEngineEntity>();
                rules.Add(new RuleEngineEntity { FieldName = "Age", Name = "CustomerCheck", Value = 25 });

                repository.LoadRuleForTest2(rules.FirstOrDefault());

                //Compile rules
                var factory = repository.Compile();

                //Create a working session
                var session = factory.CreateSession();

                RuleEngineRequestModel ruleEngineRequestModel = new RuleEngineRequestModel
                {
                    ruleList = rules,
                    customerData = new List<Customer>() { new Customer { Name = "A", Age = 28 },
                    new Customer { Name = "B", Age = 26 } }.ToArray()
                };

                session.InsertAll(ruleEngineRequestModel.customerData);

                var IspassedorNot = session.Fire();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

    public class RuleEngineRequestModel
    {
        public List<RuleEngineEntity> ruleList { get; set; }

        public Customer[] customerData { get; set; }

        public List<Customer> customerDataList { get; set; }
    }

    public class RuleEngineEntity
    {
        public string Name { get; set; }

        public int Value { get; set; }

        public string Operator { get; set; }

        public string FieldName { get; set; }

        public bool SendEmail { get; set; }

    }

    public class Customer
    {
        public string Name { get; set; }

        public int Age { get; set; }

    }

    public class CustomRuleRepository : IRuleRepository
    {
        private readonly IRuleSet _ruleSet = new RuleSet("customerRule");

        public IEnumerable<IRuleSet> GetRuleSets()
        {
            return new[] { _ruleSet };
        }

        public void LoadRuleForTest1(RuleEngineEntity rule)
        {
            _ruleSet.Add(BuildRuleForTest1(rule));
        }

        public void LoadRuleForTest2(RuleEngineEntity rule)
        {
            _ruleSet.Add(BuildRuleForTest2(rule));
        }

        public List<IRuleDefinition> BuildRuleForTest1(RuleEngineEntity rule)
        {
            return Test1(rule);
        }

        public List<IRuleDefinition> BuildRuleForTest2(RuleEngineEntity rule)
        {
            return Test2(rule);
        }


        public List<IRuleDefinition> Test1(RuleEngineEntity rule)
        {
            RuleBuilder builder = new RuleBuilder();
            builder.Name("DefaultRules");

            try
            {
                var modelPattern = builder.LeftHandSide().Pattern(typeof(Customer), "CustomerCheck");
                var modelParameter = modelPattern.Declaration.ToParameterExpression();

                var expres = Expression.Property(modelParameter, rule.FieldName);

                var binaryExpression = Expression.GreaterThan(expres, Expression.Constant(rule.Value));

                LambdaExpression expressionCondition = Expression.Lambda(binaryExpression,
                        modelParameter);


                modelPattern.Condition(expressionCondition);

                Expression<Action<IContext, Customer, RuleEngineEntity>> action =
                                 (ctx, CustomerCheck, rules) => FireActionAsync(ctx, CustomerCheck, rules);

                builder.RightHandSide().Action(action);
            }

            catch (Exception e)
            {
                // throw new Exception(e.Message);
            }

            var buildRule = builder.Build();

            return new List<IRuleDefinition> { buildRule };
        }

        public List<IRuleDefinition> Test2(RuleEngineEntity rule)
        {
            RuleBuilder builder = new RuleBuilder();
            builder.Name("DefaultRules");

            try
            {                
                   var modelPattern = builder.LeftHandSide().Pattern(typeof(RuleEngineRequestModel), "CustomerCheck");
                var modelParameter = modelPattern.Declaration.ToParameterExpression();
                var customerDataInArray = Expression.Property(modelParameter, nameof(RuleEngineRequestModel.customerData));

                var indx = Expression.Parameter(typeof(int), "index");

                var customerData = Expression.ArrayIndex(customerDataInArray, indx);

                var expres = Expression.Property(customerData, rule.FieldName);

                var binaryExpression = Expression.GreaterThan(expres, Expression.Constant(rule.Value));

                LambdaExpression expressionCondition = Expression.Lambda(binaryExpression,
                        modelParameter);

                modelPattern.Condition(expressionCondition);

                Expression<Action<IContext, Customer>> action =
                                  (ctx, CustomerCheck) => FireActionAsync(ctx, CustomerCheck, null);

                builder.RightHandSide().Action(action);
            }

            catch (Exception e)
            {
                // throw new Exception(e.Message);
            }

            var buildRule = builder.Build();

            return new List<IRuleDefinition> { buildRule };
        }

        public void FireActionAsync(IContext ctx, Customer customer, RuleEngineEntity rule=null)
        {
            Console.WriteLine($"{rule.Name} Triggered");
        }
    }

错误:从范围“”引用的“System.Int32”类型的变量“索引”,但未定义

预期:想要使用动态索引器针对数组数据验证规则。

4

1 回答 1

1

快速浏览一下,您似乎在将事实插入会话时传入了一组客户,但规则正在寻找 RuleEngineRequestModel。

另外,附注 - 为什么将数组初始化为 List,然后转换为数组,而不仅仅是初始化为数组?IE

var ruleEngineRequestModel = new RuleEngineRequestModel
{
    ruleList = rules,
    customerData = {
        new Customer { Name = "A", Age = 28 },
        new Customer { Name = "B", Age = 26 }
    }
};

最后,为什么要在插入数据的同时插入规则?这似乎会带来更多的麻烦而不是好处,尤其是当您的运行时规则构建器完全忽略它们时。

编辑:有机会看到更新的代码,这证实了我的怀疑 - 如果您对两个测试都使用规则 1,它应该可以工作(相反,它会为每个单独的客户触发)。Rule 2 从不工作的原因是因为它需要一个 RuleEngineRequestModel,但是您直接传递了 IEnumerable。要么直接传入请求模型,继续使用规则 2,要么完全废弃规则 2。

于 2019-08-30T08:07:15.090 回答