首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建动态NRules

如何创建动态NRules
EN

Stack Overflow用户
提问于 2019-02-12 17:47:43
回答 1查看 1.7K关注 0票数 1

我得到了一个例外:

代码语言:javascript
复制
variable 'e' of type 'MyClass' referenced from scope '', but it is not defined

我想用嵌套属性创建动态规则。当我创建静态规则时,它工作得很好,但不是在动态模式下。此外,如果可能的话,我希望使用以下代码行为动态规则使用表达式:

代码语言:javascript
复制
PatternBuilder customerPattern = builder.LeftHandSide().Pattern(typeof(Customer), "customer");
Expression<Func<Customer, bool>> customerCondition = customer => customer.Name == "John Do";
customerPattern.Condition(customerCondition);

我尝试了下面的代码来动态地创建和执行规则,但是我得到了一个异常。为什么?

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        try
        {
            CustomRuleRepository repository = new CustomRuleRepository();

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

            repository.LoadRules(rules);

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

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

            RuleEngineRequestModel ruleEngineRequestModel = new RuleEngineRequestModel { ruleList = rules, customerData = new Customer { Name = "A", Age = 24 } };

            session.Insert(ruleEngineRequestModel);

            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 class RuleEngineEntity
{
    public string Name { get; set; }
    public int Value { get; set; }
    public string Operator { get; set; }
    public string FieldName { 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 LoadRules(List<RuleEngineEntity> list)
    {
        _ruleSet.Add(
            BuildRule(list)
        );
    }

    public List<IRuleDefinition> BuildRule(List<RuleEngineEntity> list)
    {
        NRules.RuleModel.Builders.RuleBuilder builder = null;
        List<IRuleDefinition> rulesList = new List<IRuleDefinition>();
        builder = new NRules.RuleModel.Builders.RuleBuilder();
        builder.Name("CustomerDetail");
        ParameterExpression customerParameter = null;
        LambdaExpression customerCondition = null;
        PatternBuilder customerPattern = null;
        try
        {
            var orGroup = builder.LeftHandSide().Group(GroupType.Or);

            foreach (var item in list)
            {
                var andGroup = orGroup.Group(GroupType.And);

                customerPattern = andGroup.Pattern(typeof(RuleEngineRequestModel), item.Name);
                customerParameter = customerPattern.Declaration.ToParameterExpression();

                customerCondition =
                    Expression.Lambda(
                        Expression.GreaterThan(CreateParameterExpression(typeof(RuleEngineRequestModel), "customerData", typeof(Customer), item.FieldName),
                            Expression.Constant(item.Value)), customerParameter);
                customerPattern.Condition(customerCondition);
            }

            Expression<Action<IContext>> action =
                (ctx) => Console.WriteLine("Action triggered");

            builder.RightHandSide().Action(action);

            rulesList.Add(builder.Build());
        }
        catch (Exception e)
        {
        }

        return rulesList;
    }

    public Expression CreateParameterExpression(Type type, string propertyName, Type type2, string propertyName2)
    {
        ParameterExpression pe = Expression.Parameter(type, "e");
        Expression left = Expression.Property(pe, type.GetProperty(propertyName));
        return Expression.Property(left, type2.GetProperty(propertyName2));
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-13 01:20:30

您有一个CreateParameterExpression方法,它应该创建一个属性访问表达式。但在该方法中,您将在那里创建一个参数表达式,其名称为"e",它不对应于您在规则中定义的任何模式。这将导致“变量未找到”异常。

您只需要一个MemberExpression来访问customerData属性,然后需要另一个来访问RuleEngineEntity中配置的嵌套属性。下面是一个更新的BuildRule方法,它实现了必要的表达式树。

代码语言:javascript
复制
public List<IRuleDefinition> BuildRule(List<RuleEngineEntity> list)
{
    var builder = new NRules.RuleModel.Builders.RuleBuilder();
    builder.Name("CustomerDetail");

    var orGroup = builder.LeftHandSide().Group(GroupType.Or);

    foreach (var item in list)
    {
        var andGroup = orGroup.Group(GroupType.And);

        var modelPattern = andGroup.Pattern(typeof(RuleEngineRequestModel), item.Name);
        var modelParameter = modelPattern.Declaration.ToParameterExpression();
        var customerData = Expression.Property(modelParameter, nameof(RuleEngineRequestModel.customerData));

        var customerCondition = Expression.Lambda(
            Expression.GreaterThan(
                    Expression.Property(customerData, item.FieldName),
                    Expression.Constant(item.Value)),
                modelParameter);
        modelPattern.Condition(customerCondition);
    }

    Expression<Action<IContext>> action =
        ctx => Console.WriteLine("Action triggered");

    builder.RightHandSide().Action(action);

    var rule = builder.Build();
    return new List<IRuleDefinition> {rule};
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54655875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档