MicroExpressionEvaluator 1.0.1

dotnet add package MicroExpressionEvaluator --version 1.0.1
NuGet\Install-Package MicroExpressionEvaluator -Version 1.0.1
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="MicroExpressionEvaluator" Version="1.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MicroExpressionEvaluator --version 1.0.1
#r "nuget: MicroExpressionEvaluator, 1.0.1"
#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 MicroExpressionEvaluator as a Cake Addin
#addin nuget:?package=MicroExpressionEvaluator&version=1.0.1

// Install MicroExpressionEvaluator as a Cake Tool
#tool nuget:?package=MicroExpressionEvaluator&version=1.0.1

MicroExpressionEvaluator

Interpret and evaluate logic expressions represented as string (very quickly) and return evaluation success or throw Exception with clear Error message.

My problem

I needed something really fast (and low on CPU) at solving rules with dynamic conditions.
In my case, for dynamic and configurable rules that need to be constantly re-checked at (near) real-time.
Source of my expressions can be local or remote, contained in a json, yaml, xml, hcl or any format.

My solution

I wrote this simple and reliable .Net (Core 3.1) class library (in under 250 lines of code in one class using recursion) that can evaluate logic.

It can currently deal with types: { decimal, boolean, string }.
It understands the following operators: { "||", "&&", "!=", "==", "<=", ">=", "<", ">" }
and negation { "!" }.
It ((can simplify and solve (multiple (nested))) and (separate (logic groups))) from the ((((inside)))) out.
It splits the problem respecting the correct operator precedence (tested this implementation against C# implementation).

Runs this test class and evaluates all 74 test expressions in total of ~0,2 milliseconds! Even on my low-end Intel i5.
It uses no Regular expressions (~100x) and no scripting engines (~1000x) as these are way too slow!
It's no C++ but I find it pretty good performance wise.

It is purpose build and therefore also safer than using scripting engines. Scripting engines potentially allow scripts to cause harm and to break-out. This could be used to hijack your machine by injecting malicious payloads. At least in my use-cases this is something I need to worry about.

It required no libs, or 3rd party packages, just standard and clean .Net.
It can easily be adapted to other .Net versions or languages (TBD).

For now, it only does logic and cannot yet solve math problems (TBD).
Adding other operators, as for example: { "+", "-", "*", "/", "^", "%" } to solve simple (or more complex) math would be easy using this as a base framework.

Example In- --and--> Output

It is very low on CPU and super-fast at solving expressions such as:

7 > -7                                                      -->   Returns: true
true == true != false                                       -->   Returns: true
(true || true) && false                                     -->   Returns: false
!true == !(true || false)                                   -->   Returns: true
("text123" == "text123") && (7,00000 < 7,00001)             -->   Returns: true
10000000000,00000000000 < 10000000000,00000000001           -->   Returns: true
(false != true) && ((true || false) || (true == false))     -->   Returns: true
(false || (true == (false || (true == (false || true)))))   -->   Returns: true
(true                                                       -->   Throws (expected) exception: "Invalid input! ) expected."
-7 && 7                                                     -->   Throws (expected) exception: "Invalid input! Operator can only be applied to operands of type 'bool'."
"text123" == true                                           -->   Throws (expected) exception: "Invalid input! Operator can only be applied to operands of type 'bool'."

Real life examples

For example, I would have rules such as the following and replace the placeholders %xxx% with live values from variables then evaluate:

%CXB% == true && (%OOP% == "ACTIVE" || %OOP% == "STANDBY")
%PRE% >= 29,25 && %PRE% <= 78,5

Alternatives

These really cool projects did not work for me, or were just too slow:

  • NCalc
  • Jint
  • NLua
  • Dynamic Expresso
  • Flee
  • CS-Script
  • Roslyn (Microsoft)
  • MathParser
  • Eval Expression.NET
  • ...

Closing words

I created this a while ago, but finally managed to make the repo public.
I hope this can help you!!
Enjoy and let me know what you like, dislike or what you would do differently

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 netcoreapp3.1 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETCoreApp 3.1

    • 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.1 335 9/7/2021