C# 如何创建动态规则
我得到一个例外:C# 如何创建动态规则,c#,asp.net-core-2.1,nrules,C#,Asp.net Core 2.1,Nrules,我得到一个例外: variable 'e' of type 'MyClass' referenced from scope '', but it is not defined 我想创建具有嵌套属性的动态规则。当我创建静态规则时,它工作正常,但不是在动态模式下。此外,如果可能的话,我想使用以下代码行来表示动态规则: PatternBuilder customerPattern=builder.LeftHandSide().Pattern(typeof(Customer),“Customer”);
variable 'e' of type 'MyClass' referenced from scope '', but it is not defined
我想创建具有嵌套属性的动态规则。当我创建静态规则时,它工作正常,但不是在动态模式下。此外,如果可能的话,我想使用以下代码行来表示动态规则:
PatternBuilder customerPattern=builder.LeftHandSide().Pattern(typeof(Customer),“Customer”);
表达式customerCondition=customer=>customer.Name==“johndo”;
customerPattern.Condition(customerCondition);
我尝试了下面的代码来动态创建和执行规则,但遇到了一个异常。为什么?
类程序
{
静态void Main(字符串[]参数)
{
尝试
{
CustomRuleRepository repository=新建CustomRuleRepository();
列表规则=新列表();
添加(新规则引擎属性{FieldName=“Age”,Name=“CustomerCheck”,Value=20});
加载规则(rules);
//编译规则
var factory=repository.Compile();
//创建工作会话
var session=factory.CreateSession();
RuleEngineRequestModel RuleEngineRequestModel=new RuleEngineRequestModel{ruleList=rules,customerData=new Customer{Name=“A”,Age=24}};
插入(ruleEngineRequestModel);
var IspassedorNot=session.Fire();
}
捕获(例外e){
控制台写入线(e.Message);
}
}
}
公共类规则引擎请求模型
{
公共列表规则列表{get;set;}
公共客户客户数据{get;set;}
}
公共类规则引擎性
{
公共字符串名称{get;set;}
公共int值{get;set;}
公共字符串运算符{get;set;}
公共字符串字段名{get;set;}
}
公共类客户
{
公共字符串名称{get;set;}
公共整数{get;set;}
}
公共类CustomRuleRepository:IRuleRepository
{
私有只读IRuleSet_规则集=新规则集(“customerRule”);
公共IEnumerable GetRuleSets()
{
返回新的[]{u规则集};
}
公共无效加载规则(列表)
{
_规则集。添加(
构建规则(列表)
);
}
公共列表构建规则(列表)
{
NRules.RuleModel.Builders.RuleBuilder=null;
列表规则列表=新列表();
builder=新的NRules.RuleModel.Builders.RuleBuilder();
建造商名称(“客户详情”);
ParameterExpression customerParameter=null;
lambdexpression customerCondition=null;
PatternBuilder customerPattern=null;
尝试
{
var orGroup=builder.LeftHandSide().Group(GroupType.Or);
foreach(列表中的变量项)
{
var和Group=orGroup.Group(GroupType.And);
customerPattern=andGroup.Pattern(typeof(RuleEngineRequestModel),item.Name);
customerParameter=customerPattern.Declaration.TopParameterExpression();
顾客条件=
Lambda(
Expression.GreaterThan(CreateParameterExpression(typeof(RuleEngineRequestModel)、“customerData”、typeof(Customer)、item.FieldName),
表达式.常量(项.值)),customerParameter);
customerPattern.Condition(customerCondition);
}
表达作用=
(ctx)=>Console.WriteLine(“动作触发”);
builder.RightHandSide().Action(Action);
添加(builder.Build());
}
捕获(例外e)
{
}
返回规则列表;
}
公共表达式CreateParameterExpression(类型类型、字符串propertyName、类型type2、字符串propertyName2)
{
ParameterExpression pe=Expression.Parameter(类型“e”);
表达式left=Expression.Property(pe,type.GetProperty(propertyName));
返回表达式.Property(左,type2.GetProperty(propertyName2));
}
}
您有一个CreateParameterExpression
方法,该方法用于创建属性访问表达式。但在该方法中,您正在创建一个名为“e”的参数表达式,它与您在规则中定义的任何模式都不对应。这会导致“未找到变量”异常
您只需要一个MemberExpression来访问customerData
属性,然后另一个MemberExpression来访问在RuleEngineEntity
中配置的嵌套属性。
下面是一个更新的BuildRule
方法,它实现了必要的表达式树
公共列表构建规则(列表)
{
var builder=new NRules.RuleModel.Builders.RuleBuilder();
建造商名称(“客户详情”);
var orGroup=builder.LeftHandSide().Group(GroupType.Or);
foreach(列表中的变量项)
{
var和Group=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.Property(customerData,item.FieldName),
表达式.常量(项.值)),
模型参数);
modelPattern.Condition(客户条件);
}
表达作用=
ctx=>Console.WriteLine(“动作触发”);
builder.RightHandSide().Action(Action);
var rule=builder.Build();
返回新列表{rule};
}
谢谢您的回复,但如果我必须从传入模型访问属性,这将起作用。我之前尝试过您的方法,但我的情况是访问嵌套属性,因此在这种情况下失败。请检查我正在访问的模型和属性。@GhanshyamSingh-好的,明白了。我错过了客户被嵌套在里面