RoslynRules 1.0.5

dotnet add package RoslynRules --version 1.0.5
                    
NuGet\Install-Package RoslynRules -Version 1.0.5
                    
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="RoslynRules" Version="1.0.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RoslynRules" Version="1.0.5" />
                    
Directory.Packages.props
<PackageReference Include="RoslynRules" />
                    
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 RoslynRules --version 1.0.5
                    
#r "nuget: RoslynRules, 1.0.5"
                    
#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 RoslynRules@1.0.5
                    
#: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=RoslynRules&version=1.0.5
                    
Install as a Cake Addin
#tool nuget:?package=RoslynRules&version=1.0.5
                    
Install as a Cake Tool

RoslynRules

Turn business rules into compiled C# delegates — JSON-configurable, type-safe, and fast.

dotnet add package RoslynRules

📖 Full docs: asulwer.github.io/RoslynRules


What it does

You write rules in JSON or C#. RoslynRules compiles them to native IL delegates using the actual Roslyn compiler. No expression tree interpreters. No reflection at runtime.

The result: rules execute at near-hand-coded speed, with full compile-time validation, async support, and dependency chaining between rules.

var workflow = new Workflow
{
    Rules =
    {
        new Rule
        {
            Description = "Adult customer",
            Expression = "customer.Age >= 18",
            Action = "customer.Processed = true"
        }
    }
};

workflow.Compile(parameters);
var results = workflow.Execute(parameters);
Instead of... RoslynRules does...
Interpreting expressions at runtime Compiles to typed delegates (Roslyn → IL)
No validation until execution fails Compile-time syntax + semantic checks
Sequential-only execution Sequential, parallel, async, and streaming
No rule dependencies Topological sort + DependsOnRuleId chaining
Rules mutate after creation Immutable after Compile()
No built-in predicates 25+ static factory methods (IsNotNull, GreaterThan, etc.)
No caching Per-rule memoization with TTL

Quick start

1. Define your model

public class Customer
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
    public bool Processed { get; set; }
}

2. Create a rule

var rule = new Rule
{
    Description = "Check adult customers",
    Expression = "customer.Age >= 18",
    Action = "customer.Processed = true"
};

3. Compile and run

var parameters = new[]
{
    new RuleParameter("customer", typeof(Customer), new Customer { Name = "Alice", Age = 25 })
};

workflow.Compile(parameters);

// Run once
var result = rule.Execute(parameters);
Console.WriteLine(result.Success); // True

// Run a thousand times — zero recompilation
foreach (var customer in customers)
{
    var results = workflow.Execute(new[]
    {
        new RuleParameter("customer", typeof(Customer), customer)
    });
}

Or load rules from JSON

{
  "description": "Customer validation",
  "rules": [
    {
      "description": "Adult check",
      "expression": "customer.Age >= 18",
      "action": "customer.IsAdult = true"
    }
  ]
}
var workflow = JsonRuleLoader.LoadFromFile("rules.json");
workflow.Compile(parameters);

Multi-Parameter Rules

Rules can accept multiple parameters directly — no wrapper struct needed.

var rule = new Rule
{
    Description = "Price check",
    Expression = "price > 0 && quantity > 0",
    IsActive = true
};

var parameters = new[]
{
    new RuleParameter("price", typeof(decimal), 9.99m),
    new RuleParameter("quantity", typeof(int), 5)
};

rule.Compile(compiler, parameters);
var result = rule.Execute(parameters);

What makes it different

Not an interpreter. Most rules engines parse expressions into trees and walk them every execution. RoslynRules emits real C# assemblies via Microsoft.CodeAnalysis.CSharp. The first compile takes ~50ms. Every call after that is a direct delegate invocation — nanoseconds, not milliseconds.

Compile once, run forever. The ExpressionCompiler caches delegates in a ConcurrentDictionary. Compile a rule, and you get back the same delegate on subsequent calls. No recompilation, no assembly bloat.

Rules can depend on each other. Use DependsOnRuleId to build pipelines where one rule reads another's output. Dependencies are validated at compile time (no missing references) and resolved with topological sorting.

var validate = new Rule
{
    Description = "Validate",
    Expression = "customer.IsActive"
};

var process = new Rule
{
    Description = "Process",
    DependsOnRuleId = validate.Id,
    Expression = "context.GetResult(validate.Id).Success"
};

Async without ceremony. Expressions with await are auto-detected and compiled to async delegates. No manual Task wrapping.

new Rule
{
    Expression = "await GetPriceAsync(customer.ProductId) > 100"
};

Memory-safe by design. Compiled assemblies live in collectible AssemblyLoadContexts. After 1000 compilations (configurable), the ALC unloads and a fresh one takes over. No permanent assembly accumulation in long-running apps.

When to use it

Scenario Why RoslynRules
Business rules that change frequently JSON-driven, no redeploy needed
High-throughput validation (10K+ items/sec) Compiled delegates, parallel execution
Multi-stage approval workflows DependsOnRuleId with dependency resolution
Rules with external API calls Native async/await support
Compliance/audit requirements Per-rule logging, lifecycle events, structured results

Safety

RoslynRules compiles arbitrary C# expressions. By default, the compiler only references a whitelist of safe assemblies (System.Runtime, System.Linq, your app assembly). Dangerous namespaces like System.IO and System.Net are excluded.

Never compile expressions from untrusted sources without additional validation. See SECURITY.md for hardening guidance.

Requirements

  • .NET 8.0 or .NET 9.0 (multi-targeted)
  • Microsoft.CodeAnalysis.CSharp (pulled in via NuGet)

License

MIT — see LICENSE.txt

Product Compatible and additional computed target framework versions.
.NET 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 is compatible.  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 was computed.  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.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on RoslynRules:

Package Downloads
RoslynRules.EntityFrameworkCore

Entity Framework Core integration for RoslynRules. Provides entity models with lazy loading support while keeping the core Rule model sealed and immutable.

RoslynRules.Json

JSON serialization support for RoslynRules workflows and rules. Provides JsonRuleLoader for saving and loading rules from JSON.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.5 46 6/4/2026
1.0.4 48 6/3/2026
1.0.3 48 6/3/2026
1.0.2 53 6/1/2026
1.0.1 57 5/31/2026
1.0.0 56 5/31/2026