Hello everyone, I hope everything is going well for you. We will examine the idea of a rule engine in this post, as well as how NRule (a.NET package) implements it. We will develop a new.NET 8 desktop application to demonstrate the shopping cart discount feature for users according to their membership status (Normal/Silver/Gold/VIP) in order to facilitate comprehension.

Now let's use NRule and Rule Engine together

A software program that carries out one or more business rules in a runtime production setting is called a rule engine. The policies may be derived from corporate guidelines, statutory regulations, or other sources. You may think of a rule engine as an advanced translator of if/then statements. A rule engine's main advantage is that its business rules may be written in a non-programmer's language and can be changed without affecting the application code underneath.

NRules - An Introduction
NRules is an open-source .NET rule engine that supports defining business rules separate from the system logic. It allows for rules to be written in C#, using internal DSL to express rule conditions and actions. NRules is highly extensible, can integrate with any .NET application, and supports dynamic rule compilation.
Shopping Cart Discount Logic Using NRules

In this example, we will create a simple console application in C# that uses NRules to apply different discount percentages based on the user's membership type (Normal, Silver, Gold, VIP).

Step 1. Set Up the Project
First, create a new Console Application in Visual Studio or using the .NET CLI. Then, add the NRules package and NRules.Runtime package via NuGet.

dotnet add package NRules
dotnet add package NRules.Runtime

Step 2. Define the Domain Model
Create classes for Customers and Orders
public class Customer
{
    public string MembershipType { get; set; }
}

public class Order
{
    public Customer Customer { get; set; }
    public decimal TotalAmount { get; set; }
    public decimal DiscountedAmount { get; set; }
}


Step 3. Define the Rules
Create a class MembershipDiscountRule for discount rules. We'll consolidate the rules into a single class for simplicity.
using RuleEngine_ShoppingCartDiscount.Models;
using NRules.Fluent.Dsl;
using System;

namespace RuleEngine_ShoppingCartDiscount
{
    public class MembershipDiscountRule : Rule
    {
        public override void Define()
        {
            Order order = null;

            When()
                .Match<Order>(() => order,
                              o => o.Customer != null,
                              o => o.DiscountedAmount == 0); // Ensure discount is not already applied

            Then()
                .Do(ctx => ApplyDiscount(order))
                .Do(ctx => ctx.Update(order));
        }

        private void ApplyDiscount(Order order)
        {
            var discount = order.Customer.MembershipType switch
            {
                "Normal" => 0.90m, // 10% discount
                "Silver" => 0.80m, // 20% discount
                "Gold" => 0.75m, // 25% discount
                "VIP" => 0.70m, // 30% discount
                _ => 1.00m // No discount
            };

            order.DiscountedAmount = order.TotalAmount * discount;
            Console.WriteLine($"Applied {((1 - discount) * 100)}% discount for {order.Customer.MembershipType} member. Total now: {order.DiscountedAmount}");
        }
    }
}


Step 4. Configure and Run the Rule Engine


In your Main method, set up the rule repository, compile rules, create a session, and create the list of Customers (Normal,Silver,Gold,MVP).

// See https://aka.ms/new-console-template for more information
// Load rules
using NRules;
using NRules.Fluent;
using RuleEngine_ShoppingCartDiscount;
using RuleEngine_ShoppingCartDiscount.Models;

var repository = new RuleRepository();
repository.Load(x => x.From(typeof(MembershipDiscountRule).Assembly));

// Compile rules
var factory = repository.Compile();

// Create a session
var session = factory.CreateSession();

var customers = new List<Customer>
{
    new Customer { MembershipType = "Normal" },
    new Customer { MembershipType = "Silver" },
    new Customer { MembershipType = "Gold" },
    new Customer { MembershipType = "VIP" }
};

// Create customer and order
foreach (var customer in customers)
{
    var order = new Order { Customer = customer, TotalAmount = 100 };

    // Insert facts into rules engine's memory
    session.Insert(order);

    // Start match/resolve/act cycle
    session.Fire();

    Console.WriteLine($"Final amount to pay: {order.DiscountedAmount}\n");
}

Console.ReadLine();


Step 5. Test the Application

Run the console application and it will print the All membership-based discount price.

Code Explanation

  • Rules Definition: A single rule handles all membership types by using a switch expression to determine the discount rate based on the membership type.
  • Rule Engine Setup: Rules are loaded, and compiled, and a session is created where the order is inserted as a fact.
  • Execution: The session.Fire() method triggers the rule engine, which evaluates the inserted facts against the compiled rules and applies the appropriate discount.

HostForLIFE ASP.NET Core 9.0 Hosting

European Best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.