Afk.Expression 2.4.0

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

// Install Afk.Expression as a Cake Tool
#tool nuget:?package=Afk.Expression&version=2.4.0                

Expression

Afk.Expression is an expression parser/evaluation. Expression is parse only once and use to evaluate differents inputs (variables, constants, functions). This library can be used to generate SQL Expression to be used with Entity Framework.

Version

The library is compatible with netstandard2.0

NUGET

The easiest way to install is by using NuGet.

HowTo

This library allows you to enter complex expressions which will be evaluated and calculated on demand.

ExpressionEval eval = new ExpressionEval("5 * (3 + 8)");
Console.WriteLine(eval.Evaluate());
>>> 55

String and boolean expression can be evaluated too

ExpressionEval eval = new ExpressionEval("'one ' + 'and' + ' two'");
Console.WriteLine(eval.Evaluate());
>>> one and two
ExpressionEval eval = new ExpressionEval("true or false");
Console.WriteLine(eval.Evaluate());
>>> true

Operators

By default the ^ is the logical exclusive OR operator. You can change its behavior by using the operator type Arithmetic

ExpressionEval eval = new ExpressionEval("4^2", OperatorType.Arithmetic);
Console.WriteLine(eval.Evaluate());
>>> 16

Dates

Use the function @D to specify date with the format YYYY-MM-DD HH:MM:SS. You can specify AM and PM indicator too.

ExpressionEval eval = new ExpressionEval("@D(2022-03-08) + 1", OperatorType.Arithmetic);
Console.WriteLine(eval.Evaluate());
>>> 09/03/2022 00:00:00

Add and substract a number of whole and fractional days with operators + and -

@D(2022-08-05) + 1.5
@D(2022-08-05) - 7

Variables

Expression allows you to use variables evaluated on execution

ExpressionEval eval = new ExpressionEval("5 * x2 + y");
eval.AddVariable("x"); eval.AddVariable("y");
eval.UserExpressionEventHandler += (s, e) => {
    if (e.Name == "x")
        e.Result = 8d;
    else if (e.Name == "y")
        e.Result = 5d;
}; 
Console.WriteLine(eval.Evaluate());
>>> 325

Constants

Constants can be added to the expression

ExpressionEval eval = new ExpressionEval("pi");
eval.AddConstant("pi", 3.14);
Console.WriteLine(eval.Evaluate());
>>> 3.14

Functions

External function can be defined

    private void OnFunctionHandler(object sender, UserFunctionEventArgs e)
    {
        if (e.Name == "Concat")
        {
            e.Result = string.Join("", e.Parameters);
        }
    }

ExpressionEval eval = new ExpressionEval("Concat('The ', 'dogs ', 'barks') + '.'");
eval.AddFunctions("Concat");

eval.UserFunctionEventHandler += OnFunctionHandler;
Console.WriteLine(eval.Evaluate());
>>> The dogs barks

Custom operand

You can define custom operand to intercept binary operation on user expression if default operation don't meet your needs.

class CustomStringOperand : ICustomOperand
{
    private readonly string customValue;

    public CustomStringOperand(string customValue)
    {
        this.customValue = customValue;
    }

    public object HandleOperation(string @operator, object otherOperand, bool isLeftOperand)
    {
        if (@operator == "+" && otherOperand != null)
        {
            return (isLeftOperand) ? $"{customValue}/{otherOperand}" : $"{otherOperand}/{customValue}";
        }
        return string.Empty;
    }
}

private void OnFunctionHandler(object sender, UserFunctionEventArgs e)
{
    if (e.Name == "val1")
    {
        e.Result = new CustomStringOperand("dogs");
    }
}

ExpressionEval eval = new ExpressionEval("val1 + 'cats'");
eval.UserFunctionEventHandler += OnFunctionHandler;
Console.WriteLine(eval.Evaluate());
>>> dogs/cats

EF Core

Expression can be used to generate System.Linq.Expressions.Expression to request DbContext. You need to define a ILambdaExpressionProvider which provides expression on your entity.

class MyLambdaProvider : ILambdaExpressionProvider
{
    public Expression GetExpression(ParameterExpression parameter, string propertyName)
    {
        if (propertyName.Equals("Name", StringComparison.InvariantCultureIgnoreCase))
        {
            return System.Linq.Expressions.Expression.Property(parameter, nameof(Student.Name));
        }
        else if (propertyName.Equals("Age", StringComparison.InvariantCultureIgnoreCase))
        {
            ...
        }
        return null;
    }

Gets the expression with the extension method ToLambda on your expression :

ExpressionEval eval = new ExpressionEval("name='john'", CaseSensitivity.None);
eval.UserExpressionEventHandler += evalProperties.Evaluate;

var lambda = eval.ToLambda<Student, bool>(new MyLambdaProvider());

var result = myContext.Students.Where(lambda).ToList();

Overide operators

The ILambdaExpressionProvider enables you to override operators.

By default the like operator use the Contains method translate to CHARINDEX sql function. To overide this operator use the following definition :

class MyLambdaProvider : ILambdaExpressionProvider
{
    public Expression GetExpression(Expression left, string operand, Expression right)
    {
        if (operand == "like")
        {
            var method = typeof(DbFunctionsExtensions).GetMethod("Like", new[] { typeof(DbFunctions), typeof(string), typeof(string) });
            MethodCallExpression like = System.Linq.Expressions.Expression.Call(method, Expression.Constant(EF.Functions), left, right);
            return like;
        }
        return null;
    }
}

ExpressionEval eval = new ExpressionEval("name like '8000%'", CaseSensitivity.None);
eval.UserExpressionEventHandler += evalProperties.Evaluate;

var lambda = eval.ToLambda<Student, bool>(new MyLambdaProvider());

Console.WriteLine(lambda.ToString());
>>> "s => value(Microsoft.EntityFrameworkCore.DbFunctions).Like(s.Name, \"8000%\")"
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

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
2.4.0 60 11/20/2024
2.3.0 1,431 1/28/2023
2.2.0 300 1/28/2023
2.1.0 322 12/30/2022
2.0.0 1,415 9/4/2021
1.3.5 2,222 7/24/2020
1.3.4 1,971 2/12/2020
1.3.3 792 2/7/2020
1.3.2 867 8/29/2019
1.3.1 1,578 8/16/2019
1.3.0 655 8/7/2019
1.2.0 618 8/6/2019
1.1.0 692 7/8/2019
1.0.0 3,220 8/17/2017