Expose 1.0.0
dotnet add package Expose --version 1.0.0
NuGet\Install-Package Expose -Version 1.0.0
<PackageReference Include="Expose" Version="1.0.0" />
<PackageVersion Include="Expose" Version="1.0.0" />
<PackageReference Include="Expose" />
paket add Expose --version 1.0.0
#r "nuget: Expose, 1.0.0"
#:package Expose@1.0.0
#addin nuget:?package=Expose&version=1.0.0
#tool nuget:?package=Expose&version=1.0.0
Expose

Expose is a small C# library for composing expression trees, with full type safety and zero dependencies. It allows you to create complex expressions by calling other expressions, making it easier to build dynamic queries in a simple and intuitive way.
This can be used with LINQ, EF Core, and anything else that works with expression trees.
Installing
You can install Expose via the .NET CLI with the following command:
dotnet add package Expose
If you're using Visual Studio, you can also install via the built-in NuGet package manager.
Usage
Composing expressions:
using Expose;
Expression<Func<int, bool>> isNegative = x => x < 0;
Expression<Func<int, int>> mod2 = x => x % 2;
Expression<Func<int, bool>> composed = ExpressionComposer.SubstituteCalls(
// This replaces the .CallInline() usages with the actual expressions.
(int x) => isNegative.CallInline(x) || mod2.CallInline(x) == 1
);
Shorthand usage with LINQ and/or EF Core
To avoid having to repeat ExpressionComposer.SubstituteCalls
and specify types explicitly, you can use SubstituteCalls()
on an IQueryable
to automatically substitute all previous usages of CallInline
or CallInvoke
.
using Expose;
Expression<Func<int, bool>> isNegative = x => x < 0;
Expression<Func<int, int>> mod2 = x => x % 2;
using var context = new MyDbContext(options);
var result = await context.MyEntities
.Where(e => isNegative.CallInline(e.Age) || mod2.CallInline(e.Age) == 1)
// This replaces the .CallInline() usages with the actual expressions.
// You can chain multiple LINQ methods using .CallInline() before you call .SubstituteCalls().
.SubstituteCalls()
.ToListAsync();
Composing without inlining:
If you don't want to inline the nested methods, you can use CallInvoke()
instead of CallInline()
.
This will replace them with an InvokationExpression
instead of inlining the method body.
This may may improve compatibility with complex expressions that can't/shouldn't be inlined, but could reduce compatibility with other libraries that don't know how to interpret an InvokationExpression
node.
Similar Libraries
After writing this library, I found two other projects using similar approaches:
- LINQKit: Their
Invoke()
method is roughly equivalent to myCallInline()
method, but rather than substituting calls at the end, they useAsExpandable()
up-front which replaces calls when the IQueryable gets evaluated. - A blog post by balefrost which uses the names "Inline" and "Splice". This doesn't include any shorthands for working with
IQueryable
.
Contributing
Any contributions are welcome, but ideally start by creating an issue.
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 | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | 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.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.