मुझे यह अपवाद मिल रहा है:

variable 'e' of type 'MyClass' referenced from scope '', but it is not defined

मैं नेस्टेड संपत्ति के साथ गतिशील नियम बनाना चाहता हूँ। जब मैं स्थिर नियम बनाता हूं तो यह ठीक काम करता है, लेकिन गतिशील मोड में नहीं। साथ ही, यदि संभव हो तो मैं कोड की इन पंक्तियों का उपयोग करके गतिशील नियमों के लिए अभिव्यक्ति का उपयोग करना चाहता हूं:

PatternBuilder customerPattern = builder.LeftHandSide().Pattern(typeof(Customer), "customer");
Expression<Func<Customer, bool>> customerCondition = customer => customer.Name == "John Do";
customerPattern.Condition(customerCondition);

मैंने नियमों को गतिशील रूप से बनाने और निष्पादित करने के लिए नीचे दिए गए कोड की कोशिश की, लेकिन मुझे अपवाद मिल रहा है। क्यों?

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));
    }
}
0
Ghanshyam Singh 12 फरवरी 2019, 20:47

1 उत्तर

सबसे बढ़िया उत्तर

आपके पास एक CreateParameterExpression विधि है, जो एक प्रॉपर्टी एक्सेस एक्सप्रेशन बनाने वाली है। लेकिन उस पद्धति में आप "ई" नाम के साथ एक पैरामीटर अभिव्यक्ति बना रहे हैं, जो आपके नियम में परिभाषित किसी भी पैटर्न के अनुरूप नहीं है। यह "चर नहीं मिला" अपवाद का कारण बनता है।

customerData संपत्ति तक पहुंचने के लिए आपको बस एक MemberExpression की आवश्यकता है, और फिर RuleEngineEntity में कॉन्फ़िगर की गई नेस्टेड संपत्ति तक पहुंचने के लिए दूसरा। यहां एक अद्यतन BuildRule विधि है जो आवश्यक अभिव्यक्ति वृक्ष को लागू करती है।

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};
}
1
Sergiy Nikolayev 13 फरवरी 2019, 05:30