FunctionalDev.ExpressionHelpers 2.1.3

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

// Install FunctionalDev.ExpressionHelpers as a Cake Tool
#tool nuget:?package=FunctionalDev.ExpressionHelpers&version=2.1.3                

FunctionalDev.ExpressionHelpers

Overview

Expression Helpers is a library which has been created to enable lambda expression serialisation and deserialisation.

With the help of this library, it is possible to convert from and to string literal representations of expression trees.

For example, (Person person) => Person.FirstName == "Fred" can be converted to "FirstName = 'Fred'" and vice versa.

This typically benefits two key areas of programming, configuration and dynamic API queries. Configuration can be enhanced allowing Expression<Func<T, bool>>/Func<T, bool> types to be read from configuration.

Dynamic API queries can be implemented by enabling something along the lines of IEnumerable<T> GetModels<T>(Expression<Func<T, bool>> filter); in the client library and having the API dynamically execute the query, unlocking significant performance and extension benefits. This could be taken further and executed in a Linq to SQL layer if an ORM such as Entity Framework is in use.

Contents

  1. Basic Literals
    1. Overview - An overview of the string representation of an expression tree.
    2. Equality Comparison Operators - Comparison symbols supported by the parsers.
    3. Chaining Operators - Chaining operators supported by the parsers.
  2. Tokens - Token substitutions in expressions.
  3. Examples
    1. Calling Parser
      1. String Literal to Expression
      2. String Literal to Func
      3. Expression to String Literal
    2. Basic Equality
      1. String
      2. Integer
    3. Method Calls
      1. Constant Arguments
      2. Lambda Arguments
    4. Chaining
      1. Mixing Method And Member Comparisons
    5. Null
    6. Tokens
  4. Version Control

Basic Literals

Basic Literals - Overview

A string literal, in the context of this library, is a string which represents a serialised lambda expression. This can be broken down into segments which represent boolean conditions, chained together with chaining operators.

A string literal is built up with the following for constant/member evaluation. Members and constants can exist either side of the equation.

Constant values must be wrapped in single quotes, this denotes the internal expression as a constant value. "{Member/Constant} {Evaluation Symbol} {Member/Constant}" Methods can also be used. "{Member}.{Method Name}({Arguments as comma separated literals})" Note that nullable types and null avoidance are handled in deseralisation.

Basic Literals - Equality Comparison Operators

The following comparisons are possible.

Symbol Description
= Equals
!= Not Equals
> Greater Than
>= Greater Than or Equal
< Less Than
<= Less Than or Equal

Basic Literals - Chaining Operators

Symbol Description
And The left part of the expression must resolve to true before the right part of the expression is evaluated. Both sides must resolve to true before the full expression returns true. Comparable to AndAlso.
Or If either the left or the right side of the expression resolves to true then the full expression returns true. The right side of the Or operator is only evaluated if the left resolves to false. Comparable to OrElse.

Tokens

It is possible to tokenise a runtime expression. When calling to convert expression to string ExpressionParser.Parse use the ExpressionToken.Generate method to create a token expression which is then serialized as $Identifier$.

When calling ExpressionParser.Parse to convert from string to expression, use TokenDictionaryBuilder to provide an expression to resolve the token to.

Please see the following code for an example. Example - Tokens

Examples

For the following class, some examples are listed below.

public class Person
{
	public string FirstName { set; get; }
	public int Age { set; get; }
	public IEnumerable<Person> Friends { set; get; }
}

Examples - Calling Parser

Examples - Calling Parser - String Literal to Expression

Convert a string literal to an expression.

Expression<Func<Person, bool>> parsed = ExpressionParser.Parse<Person>("FirstName = 'Fred'");

Examples - Calling Parser - String Literal to Func

Compile the expression to a func (a delegate which can be executed at runtime).

Func<Person, bool> parsed = ExpressionParser.Parse<Person>("FirstName = 'Fred'").Compile();

Examples - Calling Parser - Expression to String Literal

Convert an expression to a string literal.

// literal will contain the value "Firstname = 'Fred'".
var literal = ExpressionParser.Parse((Person x) => x.FirstName == "Fred");

Also note that ExpressionParser contains non generic method alternatives for when the type is not known at compile time.

Examples - Basic Equality

Note that constant values are always surrounded by single quotes, integer and boolean values included.

Examples - Basic Equality - String

The following two examples compare a property to a constant value.

var basicMemberLiteral = "FirstName = 'Fred'";
var alternativeMemberLiteral = "'Fred' = FirstName";

Examples - Basic Equality - Integer

The following two examples compare a property to a constant value.

var numericalLiteral = "Age = '51'";

Examples - Method Calls

All parts of an expression literal are evaluated the same, when an argument is found for a method call it's treated in the same way, constants, method calls and literals.

Most methods could be included but the service running the parser from literal to expression must be able to understand the method calls.

Examples - Method Calls - Constant Arguments

In the example below Contains is called on the string with an argument of "F".

var methodLiteral = "FirstName.Contains('F')";

Examples - Method Calls - Lambda Arguments

In the example below a lambda is being used in the Any method call.

var nestedLambdaMethodLiteral = "Friends.Any(Age = '50')";

Examples - Chaining

Examples of chaining expression trees.

Examples - Chaining - Mixing Method And Member Comparisons

Below are some examples of mixing functions (which need to resolve to a boolean) and chaining the response with other expressions.

var chainedAndLiteral = "Friends.Any(Age = '50') And FirstName = 'Fred'";
var chainedOrLiteral = "Friends.Any(Age = '50') Or FirstName = 'Fred'";
var chainedComplexLiteral = "(Friends.Any(Age = '50') Or FirstName = 'Fred') And Age = '60'";

Examples - Null

Null can be used in an equality expression, the null text represents the Null monad.

var nullLiteral = "FirstName = null";

Examples - Tokens

Use tokens in string literals to represent a runtime substitution for a known expression.

var serializedExpression = ExpressionParser.Parse<Person>(person => person.BirthDate > ExpressionToken.Generate<DateTime>("BirthDateComp"));
// serializedExpression now contains "BirthDate > $BirthDateComp$"
var deserializedExpression = ExpressionParser.Parse<Person>(serializedExpression, new TokenDictionaryBuilder{{"BirthDateComp", () => new DateTime(1990,10,16).AddDays(5)}}.Built);
// deserializedExpression now represents the following expression:
// person => person.BirthDate > new DateTime(1990,10,16).AddDays(5)

Version Control

2.1.3 | 17/09/2024
  • Fixed endless looping on invalid expression.
2.1.1 | 07/05/2024
  • Minor readme changes: fixed content link.
2.1.1 | 07/05/2024
  • Introduced ChangeLog
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.1.3 139 9/17/2024
2.1.2 139 5/8/2024
2.1.1 112 5/7/2024
2.1.0 127 5/1/2024
2.0.1 145 4/4/2024
2.0.0 154 2/26/2024
1.1.1 137 2/7/2024
1.1.0 109 2/3/2024
1.0.4 515 1/27/2022
1.0.3 441 1/27/2022
1.0.2 433 1/26/2022
1.0.1 441 1/25/2022
1.0.0 449 1/25/2022