NRules技术咨询:如何构建匹配项的数组索引列表并在规则定义中应用
解决NRules中双列表匹配并生成索引列表的问题
首先明确核心原则:NRules的When()部分是规则的触发条件判断区,应该只做无副作用的条件检查;而数据计算、状态赋值这类操作,要放在Then()的动作执行区。你的匹配逻辑和索引列表生成,完全适合封装到自定义方法中,在Then()里调用并赋值。
一、先封装匹配与索引计算的辅助方法
把双列表的多字段匹配逻辑、索引筛选逻辑抽成独立方法,这样既保证代码复用,也符合单一职责:
// 替换YourObjectType为你实际的对象类型 private List<int> GetMatchingInboundIndexes(List<YourObjectType> inbound, List<YourObjectType> outbound) { return inbound .Select((item, index) => new { Item = item, Index = index }) // 调用下面的多字段匹配逻辑 .Where(p => DoesItemMatchOutbound(p.Item, outbound)) .Select(p => p.Index) .ToList(); } // 实现你的多字段匹配逻辑 private bool DoesItemMatchOutbound(YourObjectType inboundItem, List<YourObjectType> outbound) { // 这里替换成你实际的多字段匹配条件,比如检查字段A、字段B是否一致 return outbound.Any(outItem => outItem.FieldA == inboundItem.FieldA && outItem.FieldB == inboundItem.FieldB); }
二、修改NRules规则的Define方法
在When()里只做规则触发的必要条件判断(比如确保两个列表非空、至少存在一个匹配项),把索引计算和赋值放在Then()里执行:
public override void Define() { List<YourObjectType> inbound = null; List<YourObjectType> outbound = null; OutputObject outputObject = null; When() // 绑定内存中的inbound列表事实,可添加你的筛选条件 .Match(() => inbound, i => i != null && i.Count > 0) // 绑定内存中的outbound列表事实,可添加你的筛选条件 .Match(() => outbound, o => o != null && o.Count > 0) // 可选:添加判断,确保至少有一个匹配项才触发规则,避免空列表执行 .Exists(() => inbound, item => DoesItemMatchOutbound(item, outbound)); Then() .Do(ctx => { // 在动作执行区计算匹配索引 var matchingIndexes = GetMatchingInboundIndexes(inbound, outbound); // 将索引列表传递给输出对象处理 outputObject.ProcessMatchingIndexes(matchingIndexes); }); }
三、关键细节解释
为什么不在
When()里赋值?
NRules的When()是声明式的条件评估阶段,要求所有操作无副作用(不能修改变量、不能执行状态变更)。如果在这里做索引计算,会破坏规则评估的可预测性,甚至导致规则重复触发或异常。关于规则触发条件
示例里的Exists()是为了确保规则只在存在匹配项时才激活,避免无意义的执行。如果你的业务允许处理空索引列表,也可以去掉这个条件。变量绑定
在Define()里声明的inbound、outbound变量,会通过Match()自动绑定到内存中的对应事实对象,无需手动赋值,在Then()里可以直接使用。
内容的提问来源于stack exchange,提问作者birdus
相关产品推荐
相关产品推荐

