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
<PackageReference Include="LogicBuilder.Expressions.Utils" Version="8.0.1" />
<PackageVersion Include="LogicBuilder.Expressions.Utils" Version="8.0.1" />
<PackageReference Include="LogicBuilder.Expressions.Utils" />
paket add LogicBuilder.Expressions.Utils --version 8.0.1
#r "nuget: LogicBuilder.Expressions.Utils, 8.0.1"
#:package LogicBuilder.Expressions.Utils@8.0.1
#addin nuget:?package=LogicBuilder.Expressions.Utils&version=8.0.1
#tool nuget:?package=LogicBuilder.Expressions.Utils&version=8.0.1
LogicBuilder.Expressions.Utils
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:
- Descriptors → Operators (via AutoMapper)
- 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
Related Libraries
- 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 | Versions 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. |
-
.NETStandard 2.0
- LogicBuilder.Structures (>= 8.0.1)
- Microsoft.CSharp (>= 4.7.0)
- System.Reflection.Emit (>= 4.7.0)
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 |
Referencing the latest LogicBuilder.Structures.