Rules.Framework 1.0.27

There is a newer version of this package available.
See the version list below for details.
dotnet add package Rules.Framework --version 1.0.27                
NuGet\Install-Package Rules.Framework -Version 1.0.27                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Rules.Framework" Version="1.0.27" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Rules.Framework --version 1.0.27                
#r "nuget: Rules.Framework, 1.0.27"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Rules.Framework as a Cake Addin
#addin nuget:?package=Rules.Framework&version=1.0.27

// Install Rules.Framework as a Cake Tool
#tool nuget:?package=Rules.Framework&version=1.0.27                

Rules Framework

Rules.Framework is a generic rules framework that allows defining and evaluating rules for complex business scenarios.

Why use rules? Most of us at some point, while developing software to support a business, have come across fast paced business logic changes. Sometimes, business needs changes overnight, which requires a fast response to changes by engineering teams. By using rules, changing a calculus formula or a value mapping no longer requires code changes/endless CI/CD pipelines, QA validation, and so on... Business logic changes can be offloaded to configuration scenarios, instead of development scenarios.

Build status Quality Gate Status Nuget Package

Features

The following listing presents features implemented and features to be implemented:

  • Rules evaluation (match one)
  • Rules evaluation (match many)
  • Rules search
  • Rules content serializarion
  • Rules data source caching
  • Rules management (Create, Read, Update)
  • MongoDB data source support

How it works

First, let's start with the basics: what are we considering a rule?

A rule is a data structure limited in time (date begin and date end) which is categorized by a content type. It's application is constrained by conditions which are used to determine if it is applicable to a scenario, and also defines a priority as untie criteria when multiple rules match. A rule contains a content to be used on specific business scenario.

Confusing at first glimpse, right? Let's review the simplest sample for demonstration purposes:

Rule Sample 1

The sample rule presented:

  • Is described by it's name as "Body Mass default formula" - a simple human-readable description.
  • Has a content type "Body Mass formula" that categorizes it. This categorization is used as means to group rules during evaluation so they are evaluated together.
  • Begins at 1st January 2018 and never ends - which means that requesting on a date before 1st January 2018, rule is not matched, but after midnight at the same date, the rule will match.
  • Priority is set to 1. This would be used as untie criteria if there were more rules defined, but since there's only one rule, there's no difference on evaluation.
  • Rule has no conditions defined - which means, requesting on a date on rule dates range, it will always match.

Simple right? You got the basics covered, let's complicate this a bit by adding a new rule. The formula you saw on the first rule is used to calculate body mass when using kilograms and meters unit of measures, but what if we wanted to calculate using pounds and inches? Let's define a new rule for this:

Rule Sample 2

Newly defined rule (Rule #2):

  • Becomes the rule with priority 1.
  • Defines a new formula.
  • Defines a composed condition node specifying that a AND logical operator must be applied between child nodes conditions results.
  • Defines a condition node with data type string, having a condition type of "Mass unit of measure", operator equal and operand "pounds".
  • Defines a second condition node with data type string, having a condition type of "Height unit of measure", operator equal and operand "inches".

If you request a rule for the content type "Body Mass formula" by specifying date 2019-01-01, "Mass unit of measure" as "pounds" and "Height unit of measure" as "inches", both rules will match (remember that Rule #1 has no conditions, so it matches anything). At this point is where priority is used to untie this (by default, lowest priority values win to highest values, but this is configurable), so Rule #2 is chosen.

Remember, when you are defining rules, there are several ways on which you can define rules to match your logic needs. There's simply no silver bullet. If you need to have always a rule match, you need to find a default rule - one that matches on every scenario - and do define it, to ensure you always get a response.

Using the framework

So, how do you use the framework to have rules evaluated? Let's see how...

  1. Define your content types (suggestion: use an enum).
internal enum ContentTypes
{
    BodyMassIndexFormula = 1
}
  1. Define your condition types (suggestion: use an enum).
internal enum ConditionTypes
{
    MassUnitOfMeasure = 1,
    HeightUnitOfMeasure = 2
}
  1. Have a rules data source set up (e.g. a database). NOTE: you will have to implement your data source for the time being. There's plans to support MongoDB in the future.
public interface IRulesDataSource<TContentType, TConditionType>
{
    Task<IEnumerable<Rule<TContentType, TConditionType>>> GetRulesAsync(TContentType contentType, DateTime dateBegin, DateTime dateEnd);
}

You'll have to map each condition type defined by you to a data type on your rules data source. The ones available are:

  • Integer
  • Decimal
  • String
  • Boolean

For your guidance, check sample rules load from file: RulesFromJsonFile.cs

  1. Build a rules engine.
RulesEngineBuilder rulesEngineBuilder = new RulesEngineBuilder();

RulesEngine<ContentTypes, ConditionTypes> rulesEngine = rulesEngineBuilder.CreateRulesEngine()
    .WithContentType<ContentTypes>() // Your content types.
    .WithConditionType<ConditionTypes>() // Your condition types.
    .SetDataSource(rulesDataSource) // A rules data source instance implemented by you.
    .Build();
  1. Evalutate rule match.
Condition<ConditionTypes>[] expectedConditions = new Condition<ConditionTypes>[]
{
    new Condition<ConditionTypes>
    {
        Type = ConditionTypes.MassUnitOfMeasure,
        Value = "pounds"
    },
    new Condition<ConditionTypes>
    {
        Type = ConditionTypes.HeightUnitOfMeasure,
        Value = "inches"
    }
};

Rule<ContentTypes, ConditionTypes> ruleMatch = await rulesEngine.MatchOneAsync(ContentTypes.BodyMassIndexFormula, new DateTime(2019, 1, 1), conditions);

Contributing

Contributions are more than welcome! Submit comments, issues or pull requests, I promise to an eye on them 😃

While I try to do the best I can, suggestions/contributions are deeply appreciated on documentation!

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Rules.Framework:

Package Downloads
Rules.Framework.Providers.MongoDb

A data source provider implementation using Mongo DB for rules framework.

Rules.Framework.Providers.InMemory

A data source provider implementation using InMemory for rules framework.

Rules.Framework.WebUI

A rules framework web ui that allows you to see the rules configured in your application

Rules.Framework.Rql

A query languague implementation for rules framework - RQL.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.0-beta.1 50 6/14/2024
2.0.8 579 4/24/2024
2.0.8-beta.1 69 4/23/2024
2.0.7 249 2/5/2024
2.0.7-beta 152 1/26/2024
2.0.6 178 1/22/2024
2.0.5 223 1/4/2024
2.0.4 331 7/29/2023
2.0.3 289 7/13/2023
2.0.2 270 6/12/2023
2.0.1 252 5/22/2023
2.0.0 386 4/10/2023
1.7.7 320 2/14/2023
1.7.6 286 2/6/2023
1.7.5 1,173 1/24/2023
1.7.4 713 1/24/2023
1.7.3 789 1/11/2023
1.7.2 360 12/26/2022
1.7.0 281 12/23/2022
1.6.0 1,695 12/9/2022
1.5.1 347 11/25/2022
1.5.0 432 10/8/2022
1.4.3 440 9/23/2022
1.4.2 480 6/29/2022
1.4.1 430 6/28/2022
1.4.0 501 6/8/2022
1.3.1 2,020 3/5/2022
1.2.4 480 2/12/2022
1.2.0 535 1/21/2022
1.1.11-beta 174 1/9/2022
1.1.9-beta 178 1/8/2022
1.1.6 480 10/27/2021
1.1.5-beta 243 10/25/2021
1.1.4-beta 232 10/22/2021
1.1.3 321 10/22/2021
1.1.1-beta 237 10/11/2021
1.1.0 4,627 9/18/2021
1.0.135 331 6/20/2021
1.0.121 318 6/6/2021
1.0.114 370 4/24/2021
1.0.110 341 4/3/2021
1.0.107 703 3/31/2021
1.0.104 339 3/29/2021
1.0.97 3,618 3/28/2021
1.0.92 366 3/1/2021
1.0.69 1,284 11/22/2020
1.0.61 703 4/26/2020
1.0.56 634 4/11/2020
1.0.45 785 3/22/2020
1.0.31 495 12/7/2019
1.0.29 574 7/10/2019
1.0.27 1,564 7/9/2019