基于 XAF Blazor 的规则引擎编辑器 - 实战篇

这篇具有很好参考价值的文章主要介绍了基于 XAF Blazor 的规则引擎编辑器 - 实战篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

示例项目:https://gitee.com/easyxaf/recharge-rules-engine-sample

前言

继上一篇文章对规则引擎编辑器进行了初步介绍之后,本文将通过实际应用案例深入探讨规则引擎编辑器的使用方法。编辑器的操作相对简单,我们将重点放在RulesEngine的讲解上。请注意,本文不是RulesEngine的入门教程,如果您对RulesEngine尚不熟悉,建议先行查阅其官方文档, https://microsoft.github.io/RulesEngine

RulesEngine

这里要说一下在使用RulesEngine时的一些注意事项

RulesEngine中的Workflow类是规则信息的核心载体。它不仅包含了一个规则列表(Rules),而且每个Rule内部同样嵌套着一个规则列表。这样的设计形成了一个多层次的树状结构。然而,值得注意的是,在这个结构中,只有叶节点的表达式会被实际执行。也就是说,如果一个Rule内部的Rules列表非空,那么即使该Rule定义了表达式,它也不会被执行,它的运行结果由子Rule来决定。

对于嵌套的Rule(即子Rule),其执行方式可以通过NestedRuleExecutionMode进行配置。默认情况下,该模式设置为All,意味着所有规则都将被执行,而不考虑Rule中设置的运算符(Operator)。另一种模式是Performance,即性能模式,它会根据Rule中Operator的值来决定执行逻辑:当Operator为And或AndAlso时,如果任一子Rule返回false,则停止执行;当Operator为Or或OrElse时,如果任一子Rule返回true,则停止执行。这种模式是全局性的,适用于所有子Rule。需要注意的是,Workflow中的Rules是顶级Rule,不是嵌套Rule,不受这个设置的限制。除非有特殊需求,否则通常建议保持默认的All设置。后文将进一步介绍这两种模式的具体应用场景。

每个Rule都包含一个Actions属性,Actions同时又包含OnSuccess和OnFailure这两个子属性。需要注意的是,Workflow中的所有Rule执行完毕后,才会根据结果执行相应的OnSuccess或OnFailure动作。当Rule的结果IsSuccess为true时,将执行OnSuccess;反之,则执行OnFailure。RulesEngine内部默认提供了OutputExpressionAction和EvaluateRuleAction这两种动作。通过OutputExpressionAction,我们可以设置输出表达式。每个Rule都保存有自己的输出值,因此在规则执行完毕后,我们需要自行遍历并检索这些输出值,需要注意的是,输出结果只有一个Output属性,如果我们想区分不同的输出值,我们需要在Contenxt中设置类型信息,在读取值时再通过这个类型信息用于区分不同的值。

示例

在深入探讨之前,我想向大家推荐一个项目:http://waitmoon.com/zh/guide 。这是一个基于Java语言开发的规则引擎,该项目的设计理念和功能实现在我设计规则引擎编辑器的过程中给予了我极大的启发。接下来的示例将借鉴它文档中的案例,以助于我们更好地理解和应用规则引擎的概念。如果您对规则引擎感兴趣,或者正在寻求灵感,这个项目绝对值得一看。

示例是一个充值活动,充值返现或送积分,我先从简单开始,一步步的丰富它。

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

上面是一个最简单的规则,"充100返现5元" 与 "充50送10积分" 这两个规则在RulesEngine是顶级规则,就是它们都会被执行,如果 "充100" 那两个优惠会被叠加。如果不想被叠加,我们需要给它们创建一个父规则,如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

你会看到"充值活动"的操作符是"或"(OR),同时它底下有"一个"的字样,它还有一个选项是"全部",这是"嵌套规则输出方式",它主要针对OR操作符,这是扩展出来的功能,在上面的介绍中我们知道RulesEngine默认会执行所有规则,同时输出值会存储在每个规则结果中,这样我们可以取一个也可以取全部,你可以把"嵌套规则输出方式"看作是取输出值的标识,需要注意的是,AND操作符是没有这个选项的,因为只要一个子规则失败,父级规则就是失败的,所以也不会执行OnSuccess动作了。如上面的示例,取全部就是叠加。如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

但这里有一个注意事项,前面提到的NestedRuleExecutionMode设置,如果设置为Performance,则上面的"全部"选项则不起作用,它只会执行一个,所以如果想更灵活的使用RulesEngine,建议使用默认设置,除非确认没有上面示例中的叠加场景。

下面我们再给这个规则加个日期限制,我们可以直接修改"充值活动"为"活动日期为10.1到10.7"

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

现在面临一个问题,我们是否可以为"活动日期为10.1到10.7",直接设定一个表达式呢?根据我们之前对RulesEngine的了解,它仅执行树状结构中的叶节点表达式。这意味着,对于"活动日期为10.1到10.7"这一节点,其内部的表达式不会被执行,除非它是叶节点。然而,如果我们有一个具有多层次节点的复杂规则结构,那么为每个叶节点添加父级规则的条件将变得异常繁琐。这不仅增加了配置的复杂性,还可能导致维护上的困难。因此,我们需要寻找一种更为高效和简洁的方法来处理这种情况,来简化规则的设置过程。RulesEngine的默认执行方式我们改变不了,但我们可以在编译规则之前对规则进行一次预处理。下面是预处理代码

public static void PreProcess(this Rule rule, Rule parentRule = null)
{
    if (!string.IsNullOrWhiteSpace(parentRule?.Expression))
    {
        if (!string.IsNullOrWhiteSpace(rule.Expression))
        {
            rule.Expression = $"({parentRule.Expression}) && ({rule.Expression})";
        }
        else
        {
            rule.Expression = parentRule.Expression;
        }
    }

    if (rule.Rules != null)
    {
        foreach (var childRule in rule.Rules.ToList())
        {
            PreProcess(childRule, rule);
        }
    }
}

通过上面的扩展方法,我们可以将父级的表达式与其合并,这样叶节点就可以拥有其父级表达式了。

那如果我们再给"充50送10积分"添加一个时间限制,如"活动日期为10.5到10.7",就非常简单了,添加"活动日期为10.5到10.7"节点并为其设置表达式就可以了,如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

我们又有新的需求了,如果老客户在充值100元后,他会得到5积分,如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

大家想想上面的规则可以吗?RulesEngine总是执行叶节点,这个一定要谨记。如果新客户充100元,"老客户送5积分"不会被执行,那"充100返5元"也不会被执行,最终是选择下面的节点。

这里我们有两个处理方案

1、在不改变"充100返5元"节点的情况下,直接在其下面创建一个子规则,子规则的表达式直接返回true,这样"老客户送5积分"返回false,也不影响"充100返5元"的执行,如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

2、我们可以再优化一下,将"返现5元"放到子规则中,需要注意,当前操作符为"或",同时"嵌套规则输出方式"为"全部",如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

关于规则创建的基本概念,我们的讨论就先进行到这里。请记住,无论规则逻辑多么复杂,它们都可以通过这些基本元素逐步组合起来。通过巧妙地拼接简单的规则节点,我们可以创造出功能强大、逻辑清晰的规则逻辑。

接下来,让我们探讨一下输出。在前述示例中,涉及到了两种输出类型:"现金"和"积分",我们可以在Workflow节点下配置相应的输出类型,配置完后,我们可以在输出表达式动作(OutputExpressionAction)中选择输出类型。如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

输出表达式动作中的表达式,是 DynamicLinq的表达式语法 https://dynamic-linq.net/expression-language ,下面我们基于该表达式创建一个新的规则需求,如上面的示例"充100返5元",我们把它改为每充100返5元,也就是充值200直接返10元。如下图

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

基于 XAF Blazor 的规则引擎编辑器 - 实战篇

通过上面的表达式就可以实现"每充100返5元"

当我们设置完输出后,我们如何在执行完规则后,获取到输出值呢,下面是结合输出类型获取输出值的代码,它会返回一个字典,Key是输出类型,Value是输出值列表(每一个成功的规则结果值),后续大家可以根据自己的业务逻辑组织这一些值,上述示例,我们是对"现金"返回最大值,对"积分"是求和。

public static Dictionary<string, List<object>> GetOutputResults(this RuleResultTree resultTree)
{
    var outputResults = new Dictionary<string, List<object>>();

    if (resultTree.IsSuccess)
    {
        if (resultTree.ActionResult?.Output != null)
        {
            var context = resultTree.Rule.Actions.OnSuccess.Context;
            var outputType = context.GetValueOrDefault("type", "default") as string;
            if (!outputResults.ContainsKey(outputType))
            {
                outputResults[outputType] = [];
            }
            outputResults[outputType].Add(resultTree.ActionResult.Output);
        }
    }

    if (resultTree.ChildResults != null)
    {
        var outputMode = resultTree.Rule.Properties?.GetValueOrDefault("nestedRuleOutputMode") as string;
        foreach (var childResult in resultTree.ChildResults)
        {
            var childOutputResults = GetOutputResults(childResult);

            foreach (var childOutputResult in childOutputResults)
            {
                if (!outputResults.ContainsKey(childOutputResult.Key))
                {
                    outputResults[childOutputResult.Key] = [];
                }
                outputResults[childOutputResult.Key].AddRange(childOutputResult.Value);
            }

            if (childOutputResults.Any() && outputMode == "one")
            {
                break;
            }
        }
    }

    return outputResults;
}

下面是对输出值的处理

var outputResults = ruleResults.First().GetOutputResults();

Console.Write("共返");

if (outputResults.TryGetValue("现金", out List<object> moneyList))
{
    var money = moneyList.Select(m => double.Parse(m.ToString())).Max();
    Console.Write($"  {money}元现金");
}

if (outputResults.TryGetValue("积分", out List<object> scoreList))
{
    var score = scoreList.Select(m => double.Parse(m.ToString())).Sum();
    Console.Write($"  {score}积分");
}

写在最后

RulesEngine是一款轻量的规则引擎类库,它不仅提供了一套核心的基础功能,而且其设计具有卓越的扩展性。这使得开发者得以在此基础上构建更为强大和定制化的功能,满足各种复杂的业务逻辑需求。然而,手动编辑RulesEngine的规则文件无疑是一项耗时且繁琐的任务。正是为了减轻这一工作负担,开发规则编辑器的想法应运而生。编辑器的引入旨在简化规则的创建和管理过程,使得规则的维护变得更加高效和直观,从而将开发者从重复且繁杂的手工编辑工作中解放出来。

https://www.cnblogs.com/haoxj/p/18073710文章来源地址https://www.toymoban.com/news/detail-840154.html

到了这里,关于基于 XAF Blazor 的规则引擎编辑器 - 实战篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【富文本编辑器实战】02 编写编辑器配置文件

    本篇文章主要内容是项目的配置文件的编写与讲解,包括菜单项配置、语言配置、总体配置。 下图是编辑器的总体结构: 编辑器大致可以分为两个部分,菜单栏(图中的 1)和下面的编辑器(图中的 4)。其中菜单栏的内容较多,每个菜单项都包含了图标,说明文字(图中的 2)。部

    2024年01月21日
    浏览(57)
  • 【富文本编辑器实战】04 菜单组件和编辑器的整合

    在上一篇文章中,我们对整个编辑器项目的大体结构有了一定的了解,主要分为菜单栏和编辑区。菜单栏包括了编辑器的主要文本操作功能,且菜单项是可配置的。编辑器界面显示比较简单,是一个可编辑的 div 区域。接下来我们就来把编辑器的整体框架搭建起来,让其可以

    2024年01月24日
    浏览(73)
  • 虚幻引擎架构自动化及蓝图编辑器高级开发进修班

    课程名称:虚幻引擎架构自动化及蓝图编辑器高级开发进修班 课程介绍 大家好 我们即将推出一套课程 自动化系统开发。 自动化技术在项目开发的前中后期都大量运用。如何您是一家游戏公司,做的是网络游戏,是不是经常会遇到程序员打包加部署需要半天时间,测试demo功

    2024年04月11日
    浏览(51)
  • Activiti7工作流引擎:在线流程编辑器Activiti Modoler5.x

    有的时候我们的流程图需要业务人员自己绘制,然后使用自己绘制的流程图,此时就需要一个在线流程图编辑器需要集成到我们的web系统中。Activiti Modoler是Activiti官方推出的在线流程编辑器。 https://github.com/Activiti/Activiti/tree/5.x 将整个项目下载下来。不同版本的目录结构区别

    2024年02月09日
    浏览(55)
  • android项目实战之编辑器图片上传预览

    现状分析 项目的需求用到编辑器,编辑器中又可能用到图片上传功能。 实现方案 1. 增加依赖库,可以参考前面的几篇文章,都有描述。 2. 核心代码实现 欢迎点赞、收藏、转发。

    2024年02月04日
    浏览(68)
  • 【富文本编辑器实战】03 Vuex 的配置编写

    这里我们来看看官方网站是如何介绍 Vuex 的: 提示 这是与 Vue 3 匹配的 Vuex 4 的文档。如果您在找与 Vue 2 匹配的 Vuex 3 的文档,请在这里查看。 Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式 + 库 。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态

    2024年01月22日
    浏览(57)
  • Yjs + Quill 实现文档多人协同编辑器开发(基础+实战)

            感谢大家对文章的关注哈,大家提出的无法在不同浏览器协同的问题,经过两天多的学习研究,终于是解决了。目前版本已经正常提到 git 上了, 运行脚本:npm run startServer,是通过WebRTC 的形式实现协同(该方案仅支持内网系统,因为webRTC在外网使用需要stun 服务支

    2024年02月10日
    浏览(56)
  • 基于语雀编辑器的在线文档编辑与查看

    语雀是一个非常优秀的文档和知识库工具,其编辑器更是非常好用,虽无开源版本,但有编译好的可以使用。本文基于语雀编辑器实现在线文档的编辑与文章的预览。 参考语雀编辑器官方文档,其实现需要引入以下文件:

    2024年02月09日
    浏览(49)
  • 实战纪实 | 编辑器漏洞之Ueditor-任意文件上传漏洞 (老洞新谈)

    前言 前段时间在做某政府单位的项目的时候发现存在该漏洞,虽然是一个老洞,但这也是容易被忽视,且能快速拿到shell的漏洞,在利用方式上有一些不一样的心得,希望能帮助到一些还不太了解的小伙伴,故此写了此篇文章。 1.1 漏洞描述 Ueditor是百度开发的一个网站编辑器

    2024年04月26日
    浏览(51)
  • 二、Qt定时器与文本编辑器制作《QT 入门到实战》

    了解 qt 的 pixmap 了解 qt 的 label 如何显示图片 了解定时器的开启 了解定时器的关闭 了解文件如何进行读取 了解 QFileDialog 的使用 了解了一个文本编辑器的基本编写 巩固了 connect 的使用 在 Qt 中使用 Label 可以显示文本,但 Label 不止可以显示文本,还可以用于图片的显示。 首

    2024年02月02日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包