Build a powerful and easy-to-use rule engine in a. Net Core environment

Source: Internet
Author: User

This article source: https://github.com/jonechenug/ZHS.Nrules.Sample

1. Introduction 1.1 Why a rule engine is required

In the early days of business, it might be possible to use hard-coded or logical judgments to meet the requirements. But with the development of business, more and more problems will be exposed:

    • Logic complexity brings coding challenges, changing logic when requirements change can cause disaster
    • Repetitive requirements must be reusable, otherwise repetitive coding is required
    • Rules cannot be modified on-the-fly during runtime, but re-deployment may cause additional problems
    • Pre-launch testing becomes cumbersome and uncontrolled and requires a lot of manpower and time to test

These predicament in "Xiao Ming Adventures: Rule Engine drools Tutorial One" article can be realized, at first just simple according to the purchase amount to distribute points, the operation period also changed to more rules, if not in time to introduce the corresponding normalization processing mechanism, developers will slowly fall into the endless business abyss. The smart way to do this is to introduce a rule engine into the system, to configure rules for business operators to provide as simple an action page as possible, and to avoid coupling the rules engine and configuration to one piece.

1.2. Net Core Environment Selection--nrules

The most popular rule engine today should be drools, an open source rule engine written in the Java language, using the RETE algorithm to evaluate the rules that are written, with the following operating procedures:

For. Net applications, the rule engine operation can be invoked through the Rest interface provided by the Kie component. However, it is too large to be just a part of the core of the rule engine calculation. In this case, the open source rule engine in. NET was found, and only nrules satisfying the requirements (support for. NET Core, runtime load Rule engine) were discovered only if the Rete algorithm was also implemented.

Note: This article references the American team from 0 to 1: Build a powerful and easy-to-use rule engine in the design of the article, the Drools from the introduction to abandon.

2. Nrules actual Combat--e-commerce promotion rules engine Design 2.1 understanding Nrules

Nrules is a. NET production rules engine based on the Rete matching algorithm, based on. NET Standard, which supports 4.5+ applications, provides streaming claim rules, runtime build rules, specialized rule languages (in development, not recommended for production, based on. NET 4.5 instead. Netstandard).
Its computational mechanism is similar to other rule engines:

2.2 Design Rule Configuration

The previous article mentioned the configuration of rules for business operators to provide the simplest possible action page , so we define the rules for promotion activities as simple as possible.

In the design of the model, we must first refer to the real life encountered in the e-commerce promotion, can think of a few types of activities: full-cut promotions, single-item promotions, package promotions, gift promotions, full-gift promotions, multi-buy preferential promotions, deposit promotion.
Here, I choose to buy more preferential promotions do analysis, buy more promotional offers that is called the ladder discount, such as buy a 90 percent, buy two pieces 80 percent, the model is roughly as follows:

    public class LadderDiscountPromotion    {        public List<LadderDiscountRuleItem> Rules { get; set; }        public string Name { get; set; }        public DateTime StarTime { get; set; }        public DateTime EndTime { get; set; }        public PromotionState State { get; set; }        public List<string> ProductIdRanges { get; set; }        public bool IsSingle { get; set; }        public string Id { get; set; }    }    public class LadderDiscountRuleItem    {        /// <summary>        /// 数量        /// </summary>        public Int32 Quantity { get; set; }        /// <summary>        /// 打折的百分比        /// </summary>        public Decimal DiscountOff { get; set; }    }

In order to simplify the design, the model does not constrain the platform, the scope of activities, the membership level, etc., and only constrains the range of product IDs used. In order to match the reality may appear in the combination of offers (like the full reduction activities can also use coupons, etc.) phenomenon and the opposite of the exclusive phenomenon (such as the product does not support x-coupons after XX activities), set up a field to determine whether the offer can be combined, it can be understood that all activities are combined offers, Just some combination offers only one promotion.

Note: To learn more about e-commerce promotion system design can refer to the brain map

2.3 Rule Configuration Transformation

In order to implement the rule engine and configuration as far as possible without coupling to a piece , there must be a middle tier to convert the rule configuration to nrules acceptable rule description. By contacting the computer system of the previous article, we can get a description of this model:

    public class RuleDefinition    {        /// <summary>        /// 规则的名称        /// </summary>        public String Name { get; set; }        /// <summary>        /// 约束条件        /// </summary>        public List<LambdaExpression> Conditions { get; set; }        /// <summary>        ///  执行行动        /// </summary>        public  List<LambdaExpression> Actions { get; set; }    }

Because Nrules supports streaming declarations, both constraints and resulting results can be implemented with lambdaexpression expressions. Now we need to convert the ladder discount configuration into a rule description, so we need to analyze it first. Assuming a full 90 percent, full two pieces 80 percent, full three pieces 70 percent, then we can break it down into:

    • Greater than or equal to three pieces 70 percent
    • Greater than or equal to two pieces and less than three pieces 80 percent
    • Greater than or equal to one piece and less than two pieces 90 percent

Based on this analysis, we can see that only the first maximum number of rules is different, and the other rules are smaller than the number of previous rules and equal to the number of current rules, then we can convert our rule configuration like this:

List<ruledefinition> buildladderdiscountdefinition (ladderdiscountpromotion promotion) {var ruleDe            Finitions = new list<ruledefinition> (); By the number of effects flashback var rulelimits = promotion. Rules.orderbydescending (r = r.quantity).            ToList ();            var currentindex = 0;            var previouslimit = Rulelimits.firstordefault (); foreach (Var-in rulelimits) {//constraint expression var conditions = new List<lambda                Expression> ();                var actions = new list<lambdaexpression> ();                        if (Currentindex = = 0) {expression<func<order, bool>> Conditionpart = o = O.getrangestotalcount (promotion. productidranges) >= Current.                    Quantity; Conditions.                ADD (Conditionpart);                    } else {var limit = Previouslimit; ExprEssion<func<order, bool>> conditionpart = O = O.getrangestotalcount (promotion. productidranges) >= Current. Quantity && o.getrangestotalcount (promotion. Productidranges) < limit.                    Quantity; Conditions.                ADD (Conditionpart);                } currentindex = Currentindex + 1; Triggered behavior expression expression<action<order>> Actionpart = O = O.discountorderite MS (promotion. Productidranges, current. Discountoff, promotion. Name, promotion.                ID); Actions.                ADD (Actionpart);                    Add Description Ruledefinitions.add (new ruledefinition {actions = actions, Conditions = Conditions, Name = promotion.                Name});            Previouslimit = current;        } return ruledefinitions; }
2.4 Generating Rule collections

In Nrules's wiki, in order to implement the runtime load rule engine, we need to introduce implementation irulerepository, so we need to convert the description model to RuleSet in Nrules:

    public class Executerrepository:irulerepository, iexecuterrepository {private readonly iruleset _ruleset;        Public Executerrepository () {_ruleset = new RuleSet ("Default"); } public ienumerable<iruleset> Getrulesets () {//merge var sets = new List<irule            Set> (); Sets.            ADD (_ruleset);        return sets;            } public void AddRule (ruledefinition definition) {var builder = new Rulebuilder (); Builder. Name (definition.            Name); foreach (var condition in definition.            Conditions) {Parsepattern (builder, condition); } foreach (var action in definition. Actions) {var param = action.                Parameters.firstordefault (); var obj = GetObject (param.                Type); Builder. Righthandside (). Action (parseaction (obj, action, param.            Name)); } _ruleset.add(new[] {builder.        Build ()}); } patternbuilder Parsepattern (rulebuilder builder, lambdaexpression condition) {var parameter = Condition.            Parameters.firstordefault (); var type = parameter.            Type; var Customerpattern = Builder. Lefthandside (). Pattern (type, parameter.            Name);            Customerpattern.condition (Condition);        return customerpattern; } lambdaexpression parseaction<tentity> (TEntity entity, lambdaexpression action, String param) where TEntity        : Class, New () {return Nruleshelper.addcontext (action as expression<action<tentity>>); }    }
2.5 Execution Rule Engine

The conversion process is only the first step, we must also create a rule engine processing session, and the relevant Facts object (fact) passed to the session, executing the triggered code, the related objects have changed, its simple code is as follows:

var repository = new ExecuterRepository();//加载规则repository.AddRule(new RuleDefinition());repository.LoadRules();// 生成规则ISessionFactory factory = repository.Compile();// 创建会话ISession session = factory.CreateSession();// 加载事实对象session.Insert(new Order());// 执行session.Fire();
2.6 Scenario Examples

Let's say that there is an application Portal: Pass in a shopping cart (here equivalent to the order) ID, get the promotion that it can participate in, return the result after the promotion of the event, and in ascending order by the lowest price, then you can write:

       Public ienumerable<allpromotionfororderoutput> Allpromotionfororder ([fromquery]string ID) {            var result = new list<allpromotionfororderoutput> (); var order = _orderservice.get (ID)??            throw new ArgumentNullException ("_orderservice.get (ID)");            var promotiongroup = _promotionservice.getactivegroup ();            var Orderjson = jsonconvert.serializeobject (order); foreach (var promotions in promotiongroup) {var temporder = Jsonconvert.deserializeobject<or                Der> (Orderjson);                var ruleengineservice = HttpContext.RequestServices.GetService (typeof (Ruleengineservice)) as Ruleengineservice; Ruleengineservice.addassembly (typeof (Orderremarkrule).                Assembly);                Ruleengineservice.executepromotion (Promotions, new list<object> {Temporder                }); Result.  ADD (New Allpromotionfororderoutput (Temporder));          } return result.        (i = I.order.gettotalprice ()); }

Suppose such a shopping cart ID, buy one when the most preferential is to participate in A activity, buy two pieces when the most preferential is to participate in B and C activities, then it may be as follows:

3. Conclusion

This article simply introduces and applies the rules engine and nrules, and hides a lot of details in the process. In the sense of the power of the rule engine, it must also point out its limitations, the rule engine is also not a silver bullet, must be combined with the actual departure.

Extended reading: Martin Fowler: Should I use the rule engine?

Build a powerful and easy-to-use rule engine in a. Net Core environment

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.