EasyDecisions 1.0.45

dotnet add package EasyDecisions --version 1.0.45
                    
NuGet\Install-Package EasyDecisions -Version 1.0.45
                    
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="EasyDecisions" Version="1.0.45" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EasyDecisions" Version="1.0.45" />
                    
Directory.Packages.props
<PackageReference Include="EasyDecisions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EasyDecisions --version 1.0.45
                    
#r "nuget: EasyDecisions, 1.0.45"
                    
#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.
#:package EasyDecisions@1.0.45
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EasyDecisions&version=1.0.45
                    
Install as a Cake Addin
#tool nuget:?package=EasyDecisions&version=1.0.45
                    
Install as a Cake Tool

<div align="center"> <h1>๐ŸŽฏ EasyDecisions</h1> <p><strong>A fluent, strongly-typed, DMN-like decision engine for .NET</strong></p> <p><a href="https://mmonteiroc.github.io/easy-decisions/"><strong>Explore the Docs ยป</strong></a></p>

main SonarQube NuGet GitHub stars License: MIT </div>

<br />

๐Ÿ’ก What is EasyDecisions?

EasyDecisions is a lightweight .NET library that brings the power and clarity of Decision Model and Notation (DMN) tables directly into your C# codebase.

Instead of writing massive, deeply nested if/else or switch statements, EasyDecisions allows you to define complex business rules in a highly readable, fluent, and strongly-typed manner. It isolates your business logic from your application logic, making your code infinitely easier to read, test, and maintain.

โ“ When should I use it?

You should use EasyDecisions whenever you find yourself writing:

  • Complex mapping logic based on multiple input factors.
  • Pricing engines, discount calculators, or risk assessments.
  • State machines or status color mappers.
  • "Spaghetti code" of massive switch statements or nested if/else if blocks.
  • When you need to reuse the same decision (one input generates one output) in multiple places, avoiding the need to duplicate complex conditions or extract them into boilerplate dependency classes.

If you can imagine your business rule as a spreadsheet table (DMN), you should be using EasyDecisions.

๐Ÿš€ Installation

Install via the .NET CLI:

dotnet add package EasyDecisions

Or via the NuGet Package Manager Console:

Install-Package EasyDecisions

๐Ÿ› ๏ธ Usage

EasyDecisions offers multiple ways to define and evaluate your business rules, ranging from simple ad-hoc tables to strongly-typed class derivations and automatic factory discovery.

1. Define your Models

Inputs and Outputs can be any C# type (classes, records, or primitives). Your output must have a parameterless constructor.

public record UserContext(int Age, bool IsPremiumMember);
public class DiscountResult { public decimal Percentage { get; set; } }

2. Define your Decision

The recommended way is to inherit from Decision<TInput, TOutput>. This keeps your logic encapsulated and reusable. Rules are automatically registered, so no need for a final .Build() call.

public class DiscountDecision : Decision<UserContext, DiscountResult>
{
    public DiscountDecision() : base("DISCOUNT_CALC")
    {
        HitPolicy = HitPolicy.First;

        // You can define multiple rows (rules) in your decision table
        When(x => x.Age < 25 && x.IsPremiumMember)
            .Then()
            .Set(x => x.Percentage = 15m);

        When(x => x.IsPremiumMember)
            .Then()
            .Set(x => x.Percentage = 10m);
            
        // Default rule if nothing else matches
        When(_ => true)
            .Then()
            .Set(x => x.Percentage = 0m);
    }
}

3. Evaluate

The only way to evaluate a decision is through the EasyDecision.Evaluate helper. It finds and evaluates your decision in a single, type-safe line.

// The input type is inferred, and the result is type-safe
var result = EasyDecision.Evaluate<DiscountDecision>(userContext);

๐Ÿšฆ Hit Policies

EasyDecisions supports common DMN hit policies to control how multiple matching rules are handled. You can set the policy using .UsingHitPolicy(HitPolicy.Name).

1. Collect (Default)

Evaluates all rules. Every matching rule is applied to the output object in the order they were defined.

decision.UsingHitPolicy(HitPolicy.Collect);
// If Rule A and Rule B match, both are applied.

2. First

Returns the result of the first matching rule only. Evaluation stops immediately after a match is found.

decision.UsingHitPolicy(HitPolicy.First);
// Useful for priority-based rules (e.g., specific case before general case).

3. Unique

Ensures that exactly one rule matches. If multiple rules match the input, an InvalidOperationException is thrown.

decision.UsingHitPolicy(HitPolicy.Unique);
// The safest policy for mutually exclusive logic.

โœจ Features

  • 100% Strongly Typed: Catch errors at compile-time, not run-time.
  • Any Data Type: Supports classes, records, dictionaries, and primitive types.
  • Zero-Config Discovery: Automatic assembly scanning using DecisionFactory & [Decision].
  • Lightweight: Zero external dependencies. Fast and efficient.

๐Ÿ”ง Troubleshooting

Do I need to register decisions in my Dependency Injection (DI) container?

No. EasyDecisions requires essentially zero setup. It uses a static DecisionFactory that automatically scans your loaded assemblies the very first time you call DecisionFactory.Create(). It finds any classes decorated with the [Decision] attribute and registers them internally.

What if it says "No decision factory found" but I added the attribute?

In rare cases, if your Decision Factories are located in a completely separate project or assembly that hasn't been executed or loaded into the AppDomain yet, the automatic scanner might miss it.

You can fix this by explicitly registering that assembly anywhere in your application startup (like in your Program.cs):

// Register the assembly containing your custom decisions
DecisionFactory.RegisterAssembly(typeof(MyCustomDecision).Assembly);

๐Ÿค Contributing

Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.

๐Ÿ“ License

MIT

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 is compatible.  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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.45 45 5/6/2026
1.0.44 46 5/6/2026
1.0.43 43 5/6/2026
1.0.42 43 5/6/2026
1.0.41 44 5/6/2026
1.0.40 41 5/6/2026
1.0.39 51 5/6/2026
1.0.38 40 5/6/2026
1.0.37 40 5/6/2026
1.0.36 45 5/6/2026
1.0.35 41 5/6/2026
1.0.34 48 5/6/2026
1.0.33 45 5/6/2026
1.0.30 40 5/6/2026
1.0.24 49 5/6/2026
1.0.22 43 5/6/2026
1.0.21 38 5/6/2026
1.0.20 40 5/6/2026
1.0.16 46 5/5/2026
1.0.15 39 5/5/2026
Loading failed