LogicBuilder.Expressions.Utils 8.0.1

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

LogicBuilder.Expressions.Utils

CI CodeQL codecov Quality Gate Status NuGet

A powerful runtime expression builder that transforms metadata descriptors from LogicBuilder.Structures into executable LINQ Expression Trees. This library bridges the gap between serializable query metadata and strongly-typed, compiled LINQ expressions.

Purpose

LogicBuilder.Expressions.Utils provides the execution engine for the LogicBuilder framework. It takes descriptor metadata (POCOs from LogicBuilder.Structures) and generates fully functional LINQ expressions through a two-stage transformation:

  1. Descriptors → Operators (via AutoMapper)
  2. Operators → Expression Trees (via Build() methods)

This architecture enables:

  • Separation of concerns: Metadata structure (descriptors) separate from expression building logic (operators)
  • Serializability: Store query logic as JSON/XML, then materialize as compiled LINQ at runtime
  • Type safety: Generate strongly-typed expressions from loosely-typed metadata
  • Testability: Test expression logic using both descriptor and operator layers

Architecture

Two-Layer Design

Layer 1: Expression Operators (IExpressionPart)

Stateful objects that build LINQ Expression Trees:

  • Binary Operators: EqualsBinaryOperator, GreaterThanBinaryOperator, AndBinaryOperator, etc.
  • Unary Operators: NotOperator, ConvertOperator, CastOperator, etc.
  • Method Call Operators: ContainsOperator, StartsWithOperator, AnyOperator, AllOperator, etc.
  • Queryable Operators: WhereOperator, SelectOperator, OrderByOperator, GroupByOperator, etc.
  • Operand Operators: ParameterOperator, ConstantOperator, MemberSelectorOperator, etc.

Each operator implements IExpressionPart with a Build() method that returns a System.Linq.Expressions.Expression.

Layer 2: AutoMapper Profiles

Transform descriptors to operators:

  • An AutoMapper profile is useful for mapping descriptor classes to operator classes
  • Handles parameter scope management via mapping context
  • Preserves expression structure during transformation

e.g.:

        public void BuildFilter()
        {
            IConfigurationProvider config = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<ExpressionOperatorsMappingProfile>();
            });
            IMapper mapper = config.CreateMapper();

            Expression<Func<Product, bool>> filter = GetFilterExpression<Product>
            (
                //$it => $it.AlternateAddresses.Any(address => (address.City == "Redmond"))
                new FilterLambdaDescriptor
                (
                    new AnyDescriptor
                    (
                        new MemberSelectorDescriptor("AlternateAddresses", new ParameterDescriptor("$it")),
                        new EqualsBinaryDescriptor
                        (
                            new MemberSelectorDescriptor("City", new ParameterDescriptor("address")),
                            new ConstantDescriptor("Redmond")
                        ),
                        "address"
                    ),
                    typeof(Product),
                    "$it"
                )
            );

            Expression<Func<T, bool>> GetFilterExpression<T>(FilterLambdaDescriptor descriptor)
                => (Expression<Func<T, bool>>)mapper.Map<FilterLambdaOperator>
                (
                    descriptor,
                    opts => opts.Items["parameters"] = new Dictionary<string, ParameterExpression>()
                ).Build();
        }

        public void BuildSelector()
        {
            IConfigurationProvider config = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<ExpressionOperatorsMappingProfile>();
            });
            IMapper mapper = config.CreateMapper();

            Expression<Func<IQueryable<Category>, Category>> selector = GetSelectorExpression<IQueryable<Category>, Category>
            (
                //$it => $it.FirstOrDefault(a => (a.CategoryID == -1))
                new SelectorLambdaDescriptor
                (
                    new FirstOrDefaultDescriptor
                    (
                        new ParameterDescriptor("$it"),
                        new EqualsBinaryDescriptor
                        (
                            new MemberSelectorDescriptor("CategoryID", new ParameterDescriptor("a")),
                            new ConstantDescriptor(-1)
                        ),
                        "a"
                    ),
                    typeof(IQueryable<Category>),
                    typeof(Category),
                    "$it"
                )
            );
            
            Expression<Func<T, TResult>> GetSelectorExpression<T, TResult>(SelectorLambdaDescriptor descriptor)
                => (Expression<Func<T, TResult>>)mapper.Map<SelectorLambdaOperator>
                (
                    descriptor,
                    opts => opts.Items["parameters"] = new Dictionary<string, ParameterExpression>()
                ).Build();
        }

ExpressionOperatorsMappingProfile is a mapping profile from LogicBuilder.EntityFrameworkCore.SqlServer. The descriptor classes are fully serializable in version 8.0.0.

Requirements

  • .NET Standard 2.0 or higher
  • AutoMapper for descriptor-to-operator mapping
  • LogicBuilder.Structures for descriptor metadata classes
  • LogicBuilder.Structures: Provides descriptor metadata classes (POCOs)
  • LogicBuilder.EntityFrameworkCore.SqlServer: EF Core integration and extensive test coverage
  • LogicBuilder.Expressions.Utils.Expansions: Additional expression manipulation utilities
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.  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 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. 
.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.

NuGet packages (6)

Showing the top 5 NuGet packages that depend on LogicBuilder.Expressions.Utils:

Package Downloads
AutoMapper.AspNetCore.OData.EFCore

Creates LINQ expressions from ODataQueryOptions and executes the query.

AutoMapper.AspNetCore.OData.EF6

Creates LINQ expressions from ODataQueryOptions and executes the query.

AutoMapper.AspNet.OData.EF6

Creates LINQ expressions from ODataQueryOptions and executes the query.

LogicBuilder.Expressions.EntityFrameworkCore

Augments LogicBuilder.Expressions.Utils with LINQ queries specific to EF Core.

LogicBuilder.EntityFrameworkCore.SqlServer

Given an EF Core DBContext, LogicBuilder.EntityFrameworkCore.SqlServer uses AutoMapper configurations to support CRUD operations using the DTO objects.

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on LogicBuilder.Expressions.Utils:

Repository Stars
AutoMapper/AutoMapper.Extensions.OData
Creates LINQ expressions from ODataQueryOptions and executes the query.
Version Downloads Last Updated
8.0.1 302 5/11/2026
8.0.0 6,193 4/1/2026
7.2.0 9,593 3/16/2026
7.1.0 910 1/12/2026
7.0.0 408,866 11/25/2024
6.0.3 1,344,998 11/3/2024
6.0.2 1,119 8/11/2024
6.0.1 3,578 3/28/2024
6.0.0 1,250,640 12/27/2023
5.0.12 3,496 10/14/2023
5.0.11 200 10/14/2023
5.0.10 187,639 8/15/2023
5.0.9 871 7/16/2023
5.0.8 1,115 5/10/2023
5.0.7 5,233 10/1/2022
5.0.6 624,513 6/16/2022
5.0.4 1,223,643 4/15/2022
5.0.3 1,608 4/15/2022
5.0.2 5,335 12/24/2021
5.0.1 1,227 12/14/2021
Loading failed

Referencing the latest LogicBuilder.Structures.