Skip to content

Pattern Matching

The ExpressiveSharp source generator rewrites C# pattern-matching constructs into expression-tree-compatible ternary and binary expressions. LINQ providers translate these into their native conditional syntax (SQL CASE, MongoDB $cond/$switch, etc.).

Supported Patterns

PatternContextExample
Constantswitch arm, is1 => "one", Value is 42
Discard / defaultswitch arm_ => "other"
Typeswitch armGroupItem g => ...
Relationalswitch arm, is>= 90 => "A", Value is > 0
and combinedswitch arm, is>= 80 and < 90, Value is >= 1 and <= 100
or combinedswitch arm, is1 or 2 => "low", Value is 0 or > 100
notisName is not null
when guardswitch arm4 when IsSpecial => ...
Propertyswitch arm, isentity is { IsActive: true }
Positional / deconstructswitch arm, is(0, 0) => "origin"
List (fixed-length)is[1, 2, 3]
List (slice)is[1, .., 3]
varswitch armvar x when x > 0 => ...

is Patterns in Expression Bodies

Relational and / or

A range check using an [Expressive] helper. The tabs show how each provider translates it.

db
    .Products
    .Where(p => p.IsReasonablyPriced())
    .Select(p => p.Name)

// Setup
public static class ProductExt
{
    [Expressive]
    public static bool IsReasonablyPriced(this Product p) => p.ListPrice is >= 1m and <= 100m;
}
SELECT "p"."Name"
FROM "Products" AS "p"
WHERE ef_compare("p"."ListPrice", '1.0') >= 0 AND ef_compare("p"."ListPrice", '100.0') <= 0
SELECT p."Name"
FROM "Products" AS p
WHERE p."ListPrice" >= 1.0 AND p."ListPrice" <= 100.0
SELECT [p].[Name]
FROM [Products] AS [p]
WHERE [p].[ListPrice] >= 1.0 AND [p].[ListPrice] <= 100.0
playground.products.Aggregate([
    {
         "$match" : {
             "ListPrice" : {
                 "$gte" : { "$numberDecimal" : "1" },
                "$lte" : { "$numberDecimal" : "100" } 
            } 
        } 
    },
    {
         "$project" : { "_v" : "$Name", "_id" : 0 } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.IsReasonablyPriced_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt 
    {
        // [Expressive]
        // public static bool IsReasonablyPriced(this Product p) => p.ListPrice is >= 1m and <= 100m;
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, bool>> IsReasonablyPriced_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression() 
        {
            var p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product), "p");
            var expr_0 = global::System.Linq.Expressions.Expression.Property(p_p, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product).GetProperty("ListPrice", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.ListPrice
            var expr_3 = global::System.Linq.Expressions.Expression.Constant(1m, typeof(decimal)); // 1m
            var expr_2 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_3);
            var expr_5 = global::System.Linq.Expressions.Expression.Constant(100m, typeof(decimal)); // 100m
            var expr_4 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.LessThanOrEqual, expr_0, expr_5);
            var expr_1 = global::System.Linq.Expressions.Expression.AndAlso(expr_2, expr_4);
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, bool>>(expr_1, p_p);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("IsReasonablyPriced", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_ProductExt", "IsReasonablyPriced_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "60ChfcIqfP54N00e5AFNbaQBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<string> __Polyfill_Select_3e61_14_58(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string> __func)
        {
            // Source: p => p.Name
            var i3e6114c58_p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product), "p");
            var i3e6114c58_expr_0 = global::System.Linq.Expressions.Expression.Property(i3e6114c58_p_p, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product).GetProperty("Name", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.Name
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>>(i3e6114c58_expr_0, i3e6114c58_p_p);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Select(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product>)source,
                    __lambda));
        }
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "60ChfcIqfP54N00e5AFNbYEBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product> __Polyfill_Where_3e61_14_23(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, bool> __func)
        {
            // Source: p => p.IsReasonablyPriced()
            var i3e6114c23_p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product), "p");
            var i3e6114c23_expr_0 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("IsReasonablyPriced", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c23_p_p }); // p.IsReasonablyPriced()
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, bool>>(i3e6114c23_expr_0, i3e6114c23_p_p);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Where(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product>)source,
                    __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

Alternative values with or:

db
    .Orders
    .Where(o => o.IsBoundary())
    .Select(o => o.Id)

// Setup
public static class OrderExt
{
    [Expressive]
    public static bool IsBoundary(this Order o) => o.Items.Count is 0 or 100;
}
SELECT "o"."Id"
FROM "Orders" AS "o"
WHERE (
    SELECT COUNT(*)
    FROM "LineItems" AS "l"
    WHERE "o"."Id" = "l"."OrderId") = 0 OR (
    SELECT COUNT(*)
    FROM "LineItems" AS "l0"
    WHERE "o"."Id" = "l0"."OrderId") = 100
SELECT o."Id"
FROM "Orders" AS o
WHERE (
    SELECT count(*)::int
    FROM "LineItems" AS l
    WHERE o."Id" = l."OrderId") = 0 OR (
    SELECT count(*)::int
    FROM "LineItems" AS l0
    WHERE o."Id" = l0."OrderId") = 100
SELECT [o].[Id]
FROM [Orders] AS [o]
WHERE (
    SELECT COUNT(*)
    FROM [LineItems] AS [l]
    WHERE [o].[Id] = [l].[OrderId]) = 0 OR (
    SELECT COUNT(*)
    FROM [LineItems] AS [l0]
    WHERE [o].[Id] = [l0].[OrderId]) = 100
playground.orders.Aggregate([
    {
         "$match" : {
             "$or" : [
                {
                     "Items" : { "$size" : 0 } 
                },
                {
                     "Items" : { "$size" : 100 } 
                }
            ] 
        } 
    },
    {
         "$project" : { "_v" : "$_id", "_id" : 0 } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.IsBoundary_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt 
    {
        // [Expressive]
        // public static bool IsBoundary(this Order o) => o.Items.Count is 0 or 100;
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>> IsBoundary_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression() 
        {
            var p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var expr_1 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Items", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Items
            var expr_0 = global::System.Linq.Expressions.Expression.Property(expr_1, typeof(global::System.Collections.Generic.ICollection<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>).GetProperty("Count", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_4 = global::System.Linq.Expressions.Expression.Constant(0, typeof(int)); // 0
            var expr_3 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_4);
            var expr_6 = global::System.Linq.Expressions.Expression.Constant(100, typeof(int)); // 100
            var expr_5 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_6);
            var expr_2 = global::System.Linq.Expressions.Expression.OrElse(expr_3, expr_5);
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>>(expr_2, p_o);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("IsBoundary", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "IsBoundary_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "8CCMZGVM5dg2PK6KIFlnoJoBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<int> __Polyfill_Select_3e61_14_48(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int> __func)
        {
            // Source: o => o.Id
            var i3e6114c48_p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var i3e6114c48_expr_0 = global::System.Linq.Expressions.Expression.Property(i3e6114c48_p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Id", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Id
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int>>(i3e6114c48_expr_0, i3e6114c48_p_o);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Select(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order>)source,
                    __lambda));
        }
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "8CCMZGVM5dg2PK6KIFlnoH8BAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> __Polyfill_Where_3e61_14_21(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool> __func)
        {
            // Source: o => o.IsBoundary()
            var i3e6114c21_p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var i3e6114c21_expr_0 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("IsBoundary", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c21_p_o }); // o.IsBoundary()
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>>(i3e6114c21_expr_0, i3e6114c21_p_o);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Where(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order>)source,
                    __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

not null / not

db
    .Customers
    .Where(c => c.HasEmail())
    .Select(c => c.Name)

// Setup
public static class CustomerExt
{
    [Expressive]
    public static bool HasEmail(this Customer c) => c.Email is not null;
}
SELECT "c"."Name"
FROM "Customers" AS "c"
WHERE "c"."Email" IS NOT NULL
SELECT c."Name"
FROM "Customers" AS c
WHERE c."Email" IS NOT NULL
SELECT [c].[Name]
FROM [Customers] AS [c]
WHERE [c].[Email] IS NOT NULL
playground.customers.Aggregate([
    {
         "$match" : {
             "Email" : { "$ne" : null } 
        } 
    },
    {
         "$project" : { "_v" : "$Name", "_id" : 0 } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_CustomerExt.HasEmail_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Customer.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_CustomerExt 
    {
        // [Expressive]
        // public static bool HasEmail(this Customer c) => c.Email is not null;
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer, bool>> HasEmail_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Customer_Expression() 
        {
            var p_c = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer), "c");
            var expr_0 = global::System.Linq.Expressions.Expression.Property(p_c, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer).GetProperty("Email", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // c.Email
            var expr_4 = global::System.Linq.Expressions.Expression.Constant(null, typeof(object)); // null
            var expr_3 = global::System.Linq.Expressions.Expression.Convert(expr_4, typeof(string));
            var expr_2 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_3);
            var expr_1 = global::System.Linq.Expressions.Expression.Not(expr_2);
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer, bool>>(expr_1, p_c);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_CustomerExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_CustomerExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.CustomerExt).GetMethod("HasEmail", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_CustomerExt", "HasEmail_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Customer_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "Zp2F+472mR6pLyNY835zO5sBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<string> __Polyfill_Select_3e61_14_49(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer, string> __func)
        {
            // Source: c => c.Name
            var i3e6114c49_p_c = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer), "c");
            var i3e6114c49_expr_0 = global::System.Linq.Expressions.Expression.Property(i3e6114c49_p_c, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer).GetProperty("Name", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // c.Name
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer, string>>(i3e6114c49_expr_0, i3e6114c49_p_c);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Select(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer>)source,
                    __lambda));
        }
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "Zp2F+472mR6pLyNY835zO4IBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer> __Polyfill_Where_3e61_14_24(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer, bool> __func)
        {
            // Source: c => c.HasEmail()
            var i3e6114c24_p_c = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer), "c");
            var i3e6114c24_expr_0 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.CustomerExt).GetMethod("HasEmail", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c24_p_c }); // c.HasEmail()
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer, bool>>(i3e6114c24_expr_0, i3e6114c24_p_c);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Where(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer>)source,
                    __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

Property Patterns

db
    .Orders
    .Where(o => o.IsLargePaid())
    .Select(o => o.Id)

// Setup
public static class OrderExt
{
    [Expressive]
    public static bool IsLargePaid(this Order o) =>
        o is { Status: ExpressiveSharp.Docs.PlaygroundModel.Webshop.OrderStatus.Paid, Items.Count: > 5 };
}
.param set @Paid 1

SELECT "o"."Id"
FROM "Orders" AS "o"
WHERE "o"."Status" = @Paid AND (
    SELECT COUNT(*)
    FROM "LineItems" AS "l"
    WHERE "o"."Id" = "l"."OrderId") > 5
-- @Paid='1'
SELECT o."Id"
FROM "Orders" AS o
WHERE o."Status" = @Paid AND (
    SELECT count(*)::int
    FROM "LineItems" AS l
    WHERE o."Id" = l."OrderId") > 5
DECLARE @Paid int = 1;

SELECT [o].[Id]
FROM [Orders] AS [o]
WHERE [o].[Status] = @Paid AND (
    SELECT COUNT(*)
    FROM [LineItems] AS [l]
    WHERE [o].[Id] = [l].[OrderId]) > 5
playground.orders.Aggregate([
    {
         "$match" : {
             "$and" : [
                {
                     "$expr" : {
                         "$ne" : ["$$ROOT", null] 
                    } 
                },
                { "Status" : 1 },
                {
                     "Items" : { "$ne" : null } 
                },
                {
                     "Items.5" : { "$exists" : true } 
                }
            ] 
        } 
    },
    {
         "$project" : { "_v" : "$_id", "_id" : 0 } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.IsLargePaid_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt 
    {
        // [Expressive]
        // public static bool IsLargePaid(this Order o) => o is { Status: ExpressiveSharp.Docs.PlaygroundModel.Webshop.OrderStatus.Paid, Items.Count: > 5 };
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>> IsLargePaid_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression() 
        {
            var p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var expr_1 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order)); // o is { Status: ExpressiveSharp.Docs.PlaygroundModel.Websh...
            var expr_0 = global::System.Linq.Expressions.Expression.NotEqual(p_o, expr_1);
            var expr_2 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Status", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_4 = global::System.Linq.Expressions.Expression.Field(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.OrderStatus).GetField("Paid", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static)); // ExpressiveSharp.Docs.PlaygroundModel.Webshop.OrderStatus....
            var expr_3 = global::System.Linq.Expressions.Expression.Equal(expr_2, expr_4);
            var expr_5 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Items", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_7 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::System.Collections.Generic.ICollection<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>));
            var expr_6 = global::System.Linq.Expressions.Expression.NotEqual(expr_5, expr_7);
            var expr_8 = global::System.Linq.Expressions.Expression.Property(expr_5, typeof(global::System.Collections.Generic.ICollection<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>).GetProperty("Count", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_10 = global::System.Linq.Expressions.Expression.Constant(5, typeof(int)); // 5
            var expr_9 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, expr_8, expr_10);
            var expr_11 = global::System.Linq.Expressions.Expression.AndAlso(expr_6, expr_9);
            var expr_12 = global::System.Linq.Expressions.Expression.AndAlso(expr_0, expr_3);
            var expr_13 = global::System.Linq.Expressions.Expression.AndAlso(expr_12, expr_11);
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>>(expr_13, p_o);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("IsLargePaid", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "IsLargePaid_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "278NWZiW3VEtNWeiNnTlxJsBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<int> __Polyfill_Select_3e61_14_49(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int> __func)
        {
            // Source: o => o.Id
            var i3e6114c49_p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var i3e6114c49_expr_0 = global::System.Linq.Expressions.Expression.Property(i3e6114c49_p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Id", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Id
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int>>(i3e6114c49_expr_0, i3e6114c49_p_o);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Select(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order>)source,
                    __lambda));
        }
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "278NWZiW3VEtNWeiNnTlxH8BAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> __Polyfill_Where_3e61_14_21(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool> __func)
        {
            // Source: o => o.IsLargePaid()
            var i3e6114c21_p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var i3e6114c21_expr_0 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("IsLargePaid", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c21_p_o }); // o.IsLargePaid()
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>>(i3e6114c21_expr_0, i3e6114c21_p_o);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Where(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order>)source,
                    __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

Property patterns can be nested:

db
    .Orders
    .Where(o => o.HasNamedCustomer())
    .Select(o => o.Id)

// Setup
public static class OrderExt
{
    [Expressive]
    public static bool HasNamedCustomer(this Order o) =>
        o is { Customer: { Name: not null, Country: not null } };
}
SELECT "o"."Id"
FROM "Orders" AS "o"
INNER JOIN "Customers" AS "c" ON "o"."CustomerId" = "c"."Id"
WHERE "c"."Country" IS NOT NULL
SELECT o."Id"
FROM "Orders" AS o
INNER JOIN "Customers" AS c ON o."CustomerId" = c."Id"
WHERE c."Country" IS NOT NULL
SELECT [o].[Id]
FROM [Orders] AS [o]
INNER JOIN [Customers] AS [c] ON [o].[CustomerId] = [c].[Id]
WHERE [c].[Country] IS NOT NULL
playground.orders.Aggregate([
    {
         "$match" : {
             "$and" : [
                {
                     "$expr" : {
                         "$ne" : ["$$ROOT", null] 
                    } 
                },
                {
                     "Customer" : { "$ne" : null } 
                },
                {
                     "Customer.Name" : { "$ne" : null } 
                },
                {
                     "Customer.Country" : { "$ne" : null } 
                }
            ] 
        } 
    },
    {
         "$project" : { "_v" : "$_id", "_id" : 0 } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.HasNamedCustomer_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt 
    {
        // [Expressive]
        // public static bool HasNamedCustomer(this Order o) => o is { Customer: { Name: not null, Country: not null } };
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>> HasNamedCustomer_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression() 
        {
            var p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var expr_1 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order)); // o is { Customer: { Name: not null, Country: not null } }
            var expr_0 = global::System.Linq.Expressions.Expression.NotEqual(p_o, expr_1);
            var expr_2 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Customer", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_4 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer));
            var expr_3 = global::System.Linq.Expressions.Expression.NotEqual(expr_2, expr_4);
            var expr_5 = global::System.Linq.Expressions.Expression.Property(expr_2, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer).GetProperty("Name", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_9 = global::System.Linq.Expressions.Expression.Constant(null, typeof(object)); // null
            var expr_8 = global::System.Linq.Expressions.Expression.Convert(expr_9, typeof(string));
            var expr_7 = global::System.Linq.Expressions.Expression.Equal(expr_5, expr_8);
            var expr_6 = global::System.Linq.Expressions.Expression.Not(expr_7);
            var expr_10 = global::System.Linq.Expressions.Expression.Property(expr_2, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer).GetProperty("Country", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_14 = global::System.Linq.Expressions.Expression.Constant(null, typeof(object)); // null
            var expr_13 = global::System.Linq.Expressions.Expression.Convert(expr_14, typeof(string));
            var expr_12 = global::System.Linq.Expressions.Expression.Equal(expr_10, expr_13);
            var expr_11 = global::System.Linq.Expressions.Expression.Not(expr_12);
            var expr_15 = global::System.Linq.Expressions.Expression.AndAlso(expr_3, expr_6);
            var expr_16 = global::System.Linq.Expressions.Expression.AndAlso(expr_15, expr_11);
            var expr_17 = global::System.Linq.Expressions.Expression.AndAlso(expr_0, expr_16);
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>>(expr_17, p_o);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("HasNamedCustomer", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "HasNamedCustomer_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "IEXczphLG1wKmWqLGDNe9aABAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<int> __Polyfill_Select_3e61_14_54(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int> __func)
        {
            // Source: o => o.Id
            var i3e6114c54_p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var i3e6114c54_expr_0 = global::System.Linq.Expressions.Expression.Property(i3e6114c54_p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Id", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Id
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int>>(i3e6114c54_expr_0, i3e6114c54_p_o);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Select(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order>)source,
                    __lambda));
        }
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "IEXczphLG1wKmWqLGDNe9X8BAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> __Polyfill_Where_3e61_14_21(
            this global::ExpressiveSharp.IExpressiveQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order> source,
            global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool> __func)
        {
            // Source: o => o.HasNamedCustomer()
            var i3e6114c21_p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var i3e6114c21_expr_0 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("HasNamedCustomer", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c21_p_o }); // o.HasNamedCustomer()
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, bool>>(i3e6114c21_expr_0, i3e6114c21_p_o);
            return global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                global::System.Linq.Queryable.Where(
                    (global::System.Linq.IQueryable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order>)source,
                    __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

Positional / Deconstruct Patterns

Types that expose a Deconstruct method can use positional patterns:

csharp
[Expressive]
public string Classify(Point p) => p switch
{
    (0, 0)     => "Origin",
    (> 0, > 0) => "Quadrant 1",
    _          => "Other",
};

List Patterns

Fixed-length and slice patterns are supported on array and list types:

csharp
[Expressive]
public bool StartsWithOne(int[] arr) => arr is [1, ..];

[Expressive]
public bool IsTriple(int[] arr) => arr is [_, _, _];

Switch Expressions with Patterns

Switch expressions are the most common use of pattern matching in [Expressive] members. See Switch Expressions for a dedicated reference.

Relational and Constant Patterns

db
    .Products
    .Select(p => new { p.Name, Grade = p.GetGrade() })

// Setup
public static class ProductExt
{
    [Expressive]
    public static string GetGrade(this Product p) => p.ListPrice switch
    {
        >= 500m => "A",
        >= 100m => "B",
        >= 20m  => "C",
        _       => "F",
    };
}
SELECT "p"."Name", CASE
    WHEN ef_compare("p"."ListPrice", '500.0') >= 0 THEN 'A'
    WHEN ef_compare("p"."ListPrice", '100.0') >= 0 THEN 'B'
    WHEN ef_compare("p"."ListPrice", '20.0') >= 0 THEN 'C'
    ELSE 'F'
END AS "Grade"
FROM "Products" AS "p"
SELECT p."Name", CASE
    WHEN p."ListPrice" >= 500.0 THEN 'A'
    WHEN p."ListPrice" >= 100.0 THEN 'B'
    WHEN p."ListPrice" >= 20.0 THEN 'C'
    ELSE 'F'
END AS "Grade"
FROM "Products" AS p
SELECT [p].[Name], CASE
    WHEN [p].[ListPrice] >= 500.0 THEN N'A'
    WHEN [p].[ListPrice] >= 100.0 THEN N'B'
    WHEN [p].[ListPrice] >= 20.0 THEN N'C'
    ELSE N'F'
END AS [Grade]
FROM [Products] AS [p]
playground.products.Aggregate([
    {
         "$project" : {
             "Name" : "$Name",
            "Grade" : {
                 "$cond" : {
                     "if" : {
                         "$gte" : [
                            "$ListPrice",
                            { "$numberDecimal" : "500" }
                        ] 
                    },
                    "then" : "A",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$gte" : [
                                    "$ListPrice",
                                    { "$numberDecimal" : "100" }
                                ] 
                            },
                            "then" : "B",
                            "else" : {
                                 "$cond" : {
                                     "if" : {
                                         "$gte" : [
                                            "$ListPrice",
                                            { "$numberDecimal" : "20" }
                                        ] 
                                    },
                                    "then" : "C",
                                    "else" : "F" 
                                } 
                            } 
                        } 
                    } 
                } 
            },
            "_id" : 0 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.GetGrade_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt 
    {
        // [Expressive]
        // public static string GetGrade(this Product p) => p.ListPrice switch
        // {
        //     >= 500m => "A",
        //     >= 100m => "B",
        //     >= 20m => "C",
        //     _ => "F",
        // };
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>> GetGrade_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression() 
        {
            var p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product), "p");
            var expr_0 = global::System.Linq.Expressions.Expression.Property(p_p, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product).GetProperty("ListPrice", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.ListPrice
            var expr_1 = global::System.Linq.Expressions.Expression.Constant("F", typeof(string)); // "F"
            var expr_3 = global::System.Linq.Expressions.Expression.Constant(20m, typeof(decimal)); // 20m
            var expr_2 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_3);
            var expr_4 = global::System.Linq.Expressions.Expression.Constant("C", typeof(string)); // "C"
            var expr_5 = global::System.Linq.Expressions.Expression.Condition(expr_2, expr_4, expr_1, typeof(string));
            var expr_7 = global::System.Linq.Expressions.Expression.Constant(100m, typeof(decimal)); // 100m
            var expr_6 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_7);
            var expr_8 = global::System.Linq.Expressions.Expression.Constant("B", typeof(string)); // "B"
            var expr_9 = global::System.Linq.Expressions.Expression.Condition(expr_6, expr_8, expr_5, typeof(string));
            var expr_11 = global::System.Linq.Expressions.Expression.Constant(500m, typeof(decimal)); // 500m
            var expr_10 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_11);
            var expr_12 = global::System.Linq.Expressions.Expression.Constant("A", typeof(string)); // "A"
            var expr_13 = global::System.Linq.Expressions.Expression.Condition(expr_10, expr_12, expr_9, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>>(expr_13, p_p);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("GetGrade", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_ProductExt", "GetGrade_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "CIx299xx//nwL9fyx8jWkoEBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<T1> __Polyfill_Select_3e61_14_23<T0, T1>(
            this global::ExpressiveSharp.IExpressiveQueryable<T0> source,
            global::System.Func<T0, T1> __func)
        {
            // Source: p => new { p.Name, Grade = p.GetGrade() }
            var i3e6114c23_p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(T0), "p");
            var i3e6114c23_expr_1 = global::System.Linq.Expressions.Expression.Property(i3e6114c23_p_p, typeof(T0).GetProperty("Name", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.Name
            var i3e6114c23_expr_2 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("GetGrade", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(T0) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c23_p_p }); // p.GetGrade()
            var i3e6114c23_expr_3 = typeof(T1).GetConstructors()[0];
            var i3e6114c23_expr_0 = global::System.Linq.Expressions.Expression.New(i3e6114c23_expr_3, new global::System.Linq.Expressions.Expression[] { i3e6114c23_expr_1, i3e6114c23_expr_2 }, new global::System.Reflection.MemberInfo[] { typeof(T1).GetProperty("Name"), typeof(T1).GetProperty("Grade") });
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<T0, T1>>(i3e6114c23_expr_0, i3e6114c23_p_p);
            return (global::ExpressiveSharp.IExpressiveQueryable<T1>)(object)
                global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                    global::System.Linq.Queryable.Select(
                        (global::System.Linq.IQueryable<T0>)(object)source,
                        __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

The tabs above show how each provider renders the generated ternary chain.

and / or Combined Patterns

db
    .Products
    .Select(p => new { p.Name, Band = p.GetBand() })

// Setup
public static class ProductExt
{
    [Expressive]
    public static string GetBand(this Product p) => p.StockQuantity switch
    {
        >= 90 and <= 100 => "Excellent",
        >= 70 and < 90   => "Good",
        _                => "Poor",
    };
}
SELECT "p"."Name", CASE
    WHEN "p"."StockQuantity" >= 90 AND "p"."StockQuantity" <= 100 THEN 'Excellent'
    WHEN "p"."StockQuantity" >= 70 AND "p"."StockQuantity" < 90 THEN 'Good'
    ELSE 'Poor'
END AS "Band"
FROM "Products" AS "p"
SELECT p."Name", CASE
    WHEN p."StockQuantity" >= 90 AND p."StockQuantity" <= 100 THEN 'Excellent'
    WHEN p."StockQuantity" >= 70 AND p."StockQuantity" < 90 THEN 'Good'
    ELSE 'Poor'
END AS "Band"
FROM "Products" AS p
SELECT [p].[Name], CASE
    WHEN [p].[StockQuantity] >= 90 AND [p].[StockQuantity] <= 100 THEN N'Excellent'
    WHEN [p].[StockQuantity] >= 70 AND [p].[StockQuantity] < 90 THEN N'Good'
    ELSE N'Poor'
END AS [Band]
FROM [Products] AS [p]
playground.products.Aggregate([
    {
         "$project" : {
             "Name" : "$Name",
            "Band" : {
                 "$cond" : {
                     "if" : {
                         "$and" : [
                            {
                                 "$gte" : ["$StockQuantity", 90] 
                            },
                            {
                                 "$lte" : ["$StockQuantity", 100] 
                            }
                        ] 
                    },
                    "then" : "Excellent",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$and" : [
                                    {
                                         "$gte" : ["$StockQuantity", 70] 
                                    },
                                    {
                                         "$lt" : ["$StockQuantity", 90] 
                                    }
                                ] 
                            },
                            "then" : "Good",
                            "else" : "Poor" 
                        } 
                    } 
                } 
            },
            "_id" : 0 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.GetBand_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt 
    {
        // [Expressive]
        // public static string GetBand(this Product p) => p.StockQuantity switch
        // {
        //     >= 90 and <= 100 => "Excellent",
        //     >= 70 and < 90 => "Good",
        //     _ => "Poor",
        // };
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>> GetBand_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression() 
        {
            var p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product), "p");
            var expr_0 = global::System.Linq.Expressions.Expression.Property(p_p, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product).GetProperty("StockQuantity", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.StockQuantity
            var expr_1 = global::System.Linq.Expressions.Expression.Constant("Poor", typeof(string)); // "Poor"
            var expr_4 = global::System.Linq.Expressions.Expression.Constant(70, typeof(int)); // 70
            var expr_3 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_4);
            var expr_6 = global::System.Linq.Expressions.Expression.Constant(90, typeof(int)); // 90
            var expr_5 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.LessThan, expr_0, expr_6);
            var expr_2 = global::System.Linq.Expressions.Expression.AndAlso(expr_3, expr_5);
            var expr_7 = global::System.Linq.Expressions.Expression.Constant("Good", typeof(string)); // "Good"
            var expr_8 = global::System.Linq.Expressions.Expression.Condition(expr_2, expr_7, expr_1, typeof(string));
            var expr_11 = global::System.Linq.Expressions.Expression.Constant(90, typeof(int)); // 90
            var expr_10 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_11);
            var expr_13 = global::System.Linq.Expressions.Expression.Constant(100, typeof(int)); // 100
            var expr_12 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.LessThanOrEqual, expr_0, expr_13);
            var expr_9 = global::System.Linq.Expressions.Expression.AndAlso(expr_10, expr_12);
            var expr_14 = global::System.Linq.Expressions.Expression.Constant("Excellent", typeof(string)); // "Excellent"
            var expr_15 = global::System.Linq.Expressions.Expression.Condition(expr_9, expr_14, expr_8, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>>(expr_15, p_p);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("GetBand", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_ProductExt", "GetBand_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "AZvl2uoZvjmD4cbWTY61w4EBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<T1> __Polyfill_Select_3e61_14_23<T0, T1>(
            this global::ExpressiveSharp.IExpressiveQueryable<T0> source,
            global::System.Func<T0, T1> __func)
        {
            // Source: p => new { p.Name, Band = p.GetBand() }
            var i3e6114c23_p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(T0), "p");
            var i3e6114c23_expr_1 = global::System.Linq.Expressions.Expression.Property(i3e6114c23_p_p, typeof(T0).GetProperty("Name", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.Name
            var i3e6114c23_expr_2 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("GetBand", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(T0) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c23_p_p }); // p.GetBand()
            var i3e6114c23_expr_3 = typeof(T1).GetConstructors()[0];
            var i3e6114c23_expr_0 = global::System.Linq.Expressions.Expression.New(i3e6114c23_expr_3, new global::System.Linq.Expressions.Expression[] { i3e6114c23_expr_1, i3e6114c23_expr_2 }, new global::System.Reflection.MemberInfo[] { typeof(T1).GetProperty("Name"), typeof(T1).GetProperty("Band") });
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<T0, T1>>(i3e6114c23_expr_0, i3e6114c23_p_p);
            return (global::ExpressiveSharp.IExpressiveQueryable<T1>)(object)
                global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                    global::System.Linq.Queryable.Select(
                        (global::System.Linq.IQueryable<T0>)(object)source,
                        __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

when Guards

db
    .Products
    .Select(p => new { p.Name, Class = p.Classify() })

// Setup
public static class ProductExt
{
    [Expressive]
    public static string Classify(this Product p) => p.StockQuantity switch
    {
        4 when p.Category == "Special" => "Special Four",
        4                              => "Regular Four",
        _                              => "Other",
    };
}
SELECT "p"."Name", CASE
    WHEN "p"."StockQuantity" = 4 AND "p"."Category" = 'Special' THEN 'Special Four'
    WHEN "p"."StockQuantity" = 4 THEN 'Regular Four'
    ELSE 'Other'
END AS "Class"
FROM "Products" AS "p"
SELECT p."Name", CASE
    WHEN p."StockQuantity" = 4 AND p."Category" = 'Special' THEN 'Special Four'
    WHEN p."StockQuantity" = 4 THEN 'Regular Four'
    ELSE 'Other'
END AS "Class"
FROM "Products" AS p
SELECT [p].[Name], CASE
    WHEN [p].[StockQuantity] = 4 AND [p].[Category] = N'Special' THEN N'Special Four'
    WHEN [p].[StockQuantity] = 4 THEN N'Regular Four'
    ELSE N'Other'
END AS [Class]
FROM [Products] AS [p]
playground.products.Aggregate([
    {
         "$project" : {
             "Name" : "$Name",
            "Class" : {
                 "$cond" : {
                     "if" : {
                         "$and" : [
                            {
                                 "$eq" : ["$StockQuantity", 4] 
                            },
                            {
                                 "$eq" : ["$Category", "Special"] 
                            }
                        ] 
                    },
                    "then" : "Special Four",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$eq" : ["$StockQuantity", 4] 
                            },
                            "then" : "Regular Four",
                            "else" : "Other" 
                        } 
                    } 
                } 
            },
            "_id" : 0 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.Classify_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt 
    {
        // [Expressive]
        // public static string Classify(this Product p) => p.StockQuantity switch
        // {
        //     4 when p.Category == "Special" => "Special Four",
        //     4 => "Regular Four",
        //     _ => "Other",
        // };
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>> Classify_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression() 
        {
            var p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product), "p");
            var expr_0 = global::System.Linq.Expressions.Expression.Property(p_p, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product).GetProperty("StockQuantity", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.StockQuantity
            var expr_1 = global::System.Linq.Expressions.Expression.Constant("Other", typeof(string)); // "Other"
            var expr_3 = global::System.Linq.Expressions.Expression.Constant(4, typeof(int)); // 4
            var expr_2 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_3);
            var expr_4 = global::System.Linq.Expressions.Expression.Constant("Regular Four", typeof(string)); // "Regular Four"
            var expr_5 = global::System.Linq.Expressions.Expression.Condition(expr_2, expr_4, expr_1, typeof(string));
            var expr_7 = global::System.Linq.Expressions.Expression.Constant(4, typeof(int)); // 4
            var expr_6 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_7);
            var expr_9 = global::System.Linq.Expressions.Expression.Property(p_p, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product).GetProperty("Category", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.Category
            var expr_10 = global::System.Linq.Expressions.Expression.Constant("Special", typeof(string)); // "Special"
            var expr_8 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Equal, expr_9, expr_10);
            var expr_11 = global::System.Linq.Expressions.Expression.AndAlso(expr_6, expr_8);
            var expr_12 = global::System.Linq.Expressions.Expression.Constant("Special Four", typeof(string)); // "Special Four"
            var expr_13 = global::System.Linq.Expressions.Expression.Condition(expr_11, expr_12, expr_5, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>>(expr_13, p_p);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_ProductExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("Classify", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_ProductExt", "Classify_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Product_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "HV9ofpGne5shEsezzNgVRIEBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<T1> __Polyfill_Select_3e61_14_23<T0, T1>(
            this global::ExpressiveSharp.IExpressiveQueryable<T0> source,
            global::System.Func<T0, T1> __func)
        {
            // Source: p => new { p.Name, Class = p.Classify() }
            var i3e6114c23_p_p = global::System.Linq.Expressions.Expression.Parameter(typeof(T0), "p");
            var i3e6114c23_expr_1 = global::System.Linq.Expressions.Expression.Property(i3e6114c23_p_p, typeof(T0).GetProperty("Name", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // p.Name
            var i3e6114c23_expr_2 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.ProductExt).GetMethod("Classify", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(T0) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c23_p_p }); // p.Classify()
            var i3e6114c23_expr_3 = typeof(T1).GetConstructors()[0];
            var i3e6114c23_expr_0 = global::System.Linq.Expressions.Expression.New(i3e6114c23_expr_3, new global::System.Linq.Expressions.Expression[] { i3e6114c23_expr_1, i3e6114c23_expr_2 }, new global::System.Reflection.MemberInfo[] { typeof(T1).GetProperty("Name"), typeof(T1).GetProperty("Class") });
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<T0, T1>>(i3e6114c23_expr_0, i3e6114c23_p_p);
            return (global::ExpressiveSharp.IExpressiveQueryable<T1>)(object)
                global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                    global::System.Linq.Queryable.Select(
                        (global::System.Linq.IQueryable<T0>)(object)source,
                        __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

Type Patterns with Declaration Variables

Type patterns in switch arms produce type checks and casts:

csharp
[Expressive]
public static string Describe(this Shape shape) => shape switch
{
    Circle c    => $"Circle with radius {c.Radius}",
    Rectangle r => $"Rectangle {r.Width}x{r.Height}",
    _           => "Unknown shape",
};

TIP

Declaration variables (the c and r in the example above) are supported in switch arms. The generated expression uses type checks (is) and casts to bind the variable.

Nested Patterns

Patterns can be nested arbitrarily:

db
    .Orders
    .Select(o => new { o.Id, Tag = o.ClassifyOrder() })

// Setup
public static class OrderExt
{
    [Expressive]
    public static string ClassifyOrder(this Order o) => o switch
    {
        { Customer.Country: "US", Items.Count: >= 10 } => "VIP Order",
        { Customer: not null, Items.Count: >= 5 }      => "Standard Order",
        _                                              => "Basic Order",
    };
}
SELECT "o"."Id", "c"."Country" = 'US' AND "c"."Country" IS NOT NULL, "c"."Id", "l"."Id", "l"."OrderId", "l"."ProductId", "l"."Quantity", "l"."UnitPrice", CASE
    WHEN (
        SELECT COUNT(*)
        FROM "LineItems" AS "l0"
        WHERE "o"."Id" = "l0"."OrderId") >= 10 THEN 1
    ELSE 0
END, 1, "l1"."Id", "l1"."OrderId", "l1"."ProductId", "l1"."Quantity", "l1"."UnitPrice", CASE
    WHEN (
        SELECT COUNT(*)
        FROM "LineItems" AS "l2"
        WHERE "o"."Id" = "l2"."OrderId") >= 5 THEN 1
    ELSE 0
END
FROM "Orders" AS "o"
INNER JOIN "Customers" AS "c" ON "o"."CustomerId" = "c"."Id"
LEFT JOIN "LineItems" AS "l" ON "o"."Id" = "l"."OrderId"
LEFT JOIN "LineItems" AS "l1" ON "o"."Id" = "l1"."OrderId"
ORDER BY "o"."Id", "c"."Id", "l"."Id"
SELECT o."Id", c."Country" = 'US' AND c."Country" IS NOT NULL, c."Id", l."Id", l."OrderId", l."ProductId", l."Quantity", l."UnitPrice", CASE
    WHEN (
        SELECT count(*)::int
        FROM "LineItems" AS l0
        WHERE o."Id" = l0."OrderId") >= 10 THEN TRUE
    ELSE FALSE
END, TRUE, l1."Id", l1."OrderId", l1."ProductId", l1."Quantity", l1."UnitPrice", CASE
    WHEN (
        SELECT count(*)::int
        FROM "LineItems" AS l2
        WHERE o."Id" = l2."OrderId") >= 5 THEN TRUE
    ELSE FALSE
END
FROM "Orders" AS o
INNER JOIN "Customers" AS c ON o."CustomerId" = c."Id"
LEFT JOIN "LineItems" AS l ON o."Id" = l."OrderId"
LEFT JOIN "LineItems" AS l1 ON o."Id" = l1."OrderId"
ORDER BY o."Id", c."Id", l."Id"
SELECT [o].[Id], CASE
    WHEN [c].[Country] = N'US' AND [c].[Country] IS NOT NULL THEN CAST(1 AS bit)
    ELSE CAST(0 AS bit)
END, [c].[Id], [l].[Id], [l].[OrderId], [l].[ProductId], [l].[Quantity], [l].[UnitPrice], CASE
    WHEN (
        SELECT COUNT(*)
        FROM [LineItems] AS [l0]
        WHERE [o].[Id] = [l0].[OrderId]) >= 10 THEN CAST(1 AS bit)
    ELSE CAST(0 AS bit)
END, CAST(1 AS bit), [l1].[Id], [l1].[OrderId], [l1].[ProductId], [l1].[Quantity], [l1].[UnitPrice], CASE
    WHEN (
        SELECT COUNT(*)
        FROM [LineItems] AS [l2]
        WHERE [o].[Id] = [l2].[OrderId]) >= 5 THEN CAST(1 AS bit)
    ELSE CAST(0 AS bit)
END
FROM [Orders] AS [o]
INNER JOIN [Customers] AS [c] ON [o].[CustomerId] = [c].[Id]
LEFT JOIN [LineItems] AS [l] ON [o].[Id] = [l].[OrderId]
LEFT JOIN [LineItems] AS [l1] ON [o].[Id] = [l1].[OrderId]
ORDER BY [o].[Id], [c].[Id], [l].[Id]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Tag" : {
                 "$cond" : {
                     "if" : {
                         "$and" : [
                            {
                                 "$ne" : ["$$ROOT", null] 
                            },
                            {
                                 "$ne" : ["$Customer", null] 
                            },
                            {
                                 "$eq" : ["$Customer.Country", "US"] 
                            },
                            {
                                 "$ne" : ["$Items", null] 
                            },
                            {
                                 "$gte" : [
                                    { "$size" : "$Items" },
                                    10
                                ] 
                            }
                        ] 
                    },
                    "then" : "VIP Order",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$and" : [
                                    {
                                         "$ne" : ["$$ROOT", null] 
                                    },
                                    {
                                         "$not" : {
                                             "$eq" : ["$Customer", null] 
                                        } 
                                    },
                                    {
                                         "$ne" : ["$Items", null] 
                                    },
                                    {
                                         "$gte" : [
                                            { "$size" : "$Items" },
                                            5
                                        ] 
                                    }
                                ] 
                            },
                            "then" : "Standard Order",
                            "else" : "Basic Order" 
                        } 
                    } 
                } 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.ClassifyOrder_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Linq;
using System.Linq.Expressions;
using ExpressiveSharp;
using ExpressiveSharp.EntityFrameworkCore;
using ExpressiveSharp.Docs.PlaygroundModel.Webshop;
using ExpressiveSharp.Docs.Playground.Snippet;

namespace ExpressiveSharp.Generated
{
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt 
    {
        // [Expressive]
        // public static string ClassifyOrder(this Order o) => o switch
        // {
        //     { Customer.Country: "US", Items.Count: >= 10 } => "VIP Order",
        //     { Customer: not null, Items.Count: >= 5 } => "Standard Order",
        //     _ => "Basic Order",
        // };
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>> ClassifyOrder_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression() 
        {
            var p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order), "o");
            var expr_0 = global::System.Linq.Expressions.Expression.Constant("Basic Order", typeof(string)); // "Basic Order"
            var expr_2 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order));
            var expr_1 = global::System.Linq.Expressions.Expression.NotEqual(p_o, expr_2);
            var expr_3 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Customer", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_7 = global::System.Linq.Expressions.Expression.Constant(null, typeof(object)); // null
            var expr_6 = global::System.Linq.Expressions.Expression.Convert(expr_7, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer));
            var expr_5 = global::System.Linq.Expressions.Expression.Equal(expr_3, expr_6);
            var expr_4 = global::System.Linq.Expressions.Expression.Not(expr_5);
            var expr_8 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Items", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_10 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::System.Collections.Generic.ICollection<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>));
            var expr_9 = global::System.Linq.Expressions.Expression.NotEqual(expr_8, expr_10);
            var expr_11 = global::System.Linq.Expressions.Expression.Property(expr_8, typeof(global::System.Collections.Generic.ICollection<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>).GetProperty("Count", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_13 = global::System.Linq.Expressions.Expression.Constant(5, typeof(int)); // 5
            var expr_12 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_11, expr_13);
            var expr_14 = global::System.Linq.Expressions.Expression.AndAlso(expr_9, expr_12);
            var expr_15 = global::System.Linq.Expressions.Expression.AndAlso(expr_1, expr_4);
            var expr_16 = global::System.Linq.Expressions.Expression.AndAlso(expr_15, expr_14);
            var expr_17 = global::System.Linq.Expressions.Expression.Constant("Standard Order", typeof(string)); // "Standard Order"
            var expr_18 = global::System.Linq.Expressions.Expression.Condition(expr_16, expr_17, expr_0, typeof(string));
            var expr_20 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order));
            var expr_19 = global::System.Linq.Expressions.Expression.NotEqual(p_o, expr_20);
            var expr_21 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Customer", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_23 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer));
            var expr_22 = global::System.Linq.Expressions.Expression.NotEqual(expr_21, expr_23);
            var expr_24 = global::System.Linq.Expressions.Expression.Property(expr_21, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Customer).GetProperty("Country", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_26 = global::System.Linq.Expressions.Expression.Constant("US", typeof(string)); // "US"
            var expr_25 = global::System.Linq.Expressions.Expression.Equal(expr_24, expr_26);
            var expr_27 = global::System.Linq.Expressions.Expression.AndAlso(expr_22, expr_25);
            var expr_28 = global::System.Linq.Expressions.Expression.Property(p_o, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order).GetProperty("Items", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_30 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::System.Collections.Generic.ICollection<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>));
            var expr_29 = global::System.Linq.Expressions.Expression.NotEqual(expr_28, expr_30);
            var expr_31 = global::System.Linq.Expressions.Expression.Property(expr_28, typeof(global::System.Collections.Generic.ICollection<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>).GetProperty("Count", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_33 = global::System.Linq.Expressions.Expression.Constant(10, typeof(int)); // 10
            var expr_32 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_31, expr_33);
            var expr_34 = global::System.Linq.Expressions.Expression.AndAlso(expr_29, expr_32);
            var expr_35 = global::System.Linq.Expressions.Expression.AndAlso(expr_19, expr_27);
            var expr_36 = global::System.Linq.Expressions.Expression.AndAlso(expr_35, expr_34);
            var expr_37 = global::System.Linq.Expressions.Expression.Constant("VIP Order", typeof(string)); // "VIP Order"
            var expr_38 = global::System.Linq.Expressions.Expression.Condition(expr_36, expr_37, expr_18, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>>(expr_38, p_o);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.Attributes.g.cs ===
// <auto-generated/>

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    static partial class ExpressiveSharp_Docs_Playground_Snippet_OrderExt { }
}


// === ExpressionRegistry.g.cs ===
// <auto-generated/>
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressiveSharp.Generated
{
    [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
    internal static class ExpressionRegistry
    {
        private static Dictionary<nint, LambdaExpression> Build()
        {
            const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            var map = new Dictionary<nint, LambdaExpression>();
            
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("ClassifyOrder", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "ClassifyOrder_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression");
            
            return map;
        }
        
        private static volatile Dictionary<nint, LambdaExpression> _map = Build();
        
        internal static void ResetMap() => _map = Build();
        
        public static LambdaExpression TryGet(MemberInfo member)
        {
            var handle = member switch
            {
                MethodInfo m      => (nint?)m.MethodHandle.Value,
                PropertyInfo p    => p.GetMethod?.MethodHandle.Value,
                ConstructorInfo c => (nint?)c.MethodHandle.Value,
                _                 => null
            };
            
            return handle.HasValue && _map.TryGetValue(handle.Value, out var expr) ? expr : null;
        }
        
        private static void Register(Dictionary<nint, LambdaExpression> map, MethodBase m, string exprClass, string exprMethodName)
        {
            if (m is null) return;
            var exprType = m.DeclaringType?.Assembly.GetType(exprClass) ?? typeof(ExpressionRegistry).Assembly.GetType(exprClass);
            var exprMethod = exprType?.GetMethod(exprMethodName, BindingFlags.Static | BindingFlags.NonPublic);
            if (exprMethod is null) return;
            var expr = (LambdaExpression)exprMethod.Invoke(null, null)!;
            
            // Apply declared transformers from the generated class (if any)
            const string expressionSuffix = "_Expression";
            if (exprMethodName.EndsWith(expressionSuffix, StringComparison.Ordinal))
            {
                var transformersSuffix = exprMethodName.Substring(0, exprMethodName.Length - expressionSuffix.Length) + "_Transformers";
                var transformersMethod = exprType.GetMethod(transformersSuffix, BindingFlags.Static | BindingFlags.NonPublic);
                if (transformersMethod?.Invoke(null, null) is global::ExpressiveSharp.IExpressionTreeTransformer[] transformers)
                {
                    Expression transformed = expr;
                    foreach (var t in transformers) transformed = t.Transform(transformed);
                    if (transformed is LambdaExpression lambdaResult) expr = lambdaResult;
                }
            }
            
            map[m.MethodHandle.Value] = expr;
        }
    }
}


// === PolyfillInterceptors_b1293e61.g.cs ===
// <auto-generated/>
#nullable disable

namespace ExpressiveSharp.Generated.Interceptors
{
    internal static partial class PolyfillInterceptors
    {
        [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "m/9rAoVVUikWXuWxfqLH9H8BAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<T1> __Polyfill_Select_3e61_14_21<T0, T1>(
            this global::ExpressiveSharp.IExpressiveQueryable<T0> source,
            global::System.Func<T0, T1> __func)
        {
            // Source: o => new { o.Id, Tag = o.ClassifyOrder() }
            var i3e6114c21_p_o = global::System.Linq.Expressions.Expression.Parameter(typeof(T0), "o");
            var i3e6114c21_expr_1 = global::System.Linq.Expressions.Expression.Property(i3e6114c21_p_o, typeof(T0).GetProperty("Id", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Id
            var i3e6114c21_expr_2 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("ClassifyOrder", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static, null, new global::System.Type[] { typeof(T0) }, null), new global::System.Linq.Expressions.Expression[] { i3e6114c21_p_o }); // o.ClassifyOrder()
            var i3e6114c21_expr_3 = typeof(T1).GetConstructors()[0];
            var i3e6114c21_expr_0 = global::System.Linq.Expressions.Expression.New(i3e6114c21_expr_3, new global::System.Linq.Expressions.Expression[] { i3e6114c21_expr_1, i3e6114c21_expr_2 }, new global::System.Reflection.MemberInfo[] { typeof(T1).GetProperty("Id"), typeof(T1).GetProperty("Tag") });
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<T0, T1>>(i3e6114c21_expr_0, i3e6114c21_p_o);
            return (global::ExpressiveSharp.IExpressiveQueryable<T1>)(object)
                global::ExpressiveSharp.ExpressiveQueryableExtensions.AsExpressive(
                    global::System.Linq.Queryable.Select(
                        (global::System.Linq.IQueryable<T0>)(object)source,
                        __lambda));
        }
    }
}

namespace System.Runtime.CompilerServices
{
    [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : global::System.Attribute
    {
        public InterceptsLocationAttribute(int version, string data) { }
    }
}

Translation Output

All pattern-matching constructs compile down to nested conditional expressions. The generator produces a chain of ternaries, which each provider maps to its own conditional syntax (SQL CASE WHEN ... THEN ... ELSE ... END, MongoDB $switch/$cond, etc.). The tabs on the samples above let you inspect the exact translation for your target.

WARNING

Keep patterns reasonably simple for translation. Very deeply nested patterns produce complex output that may be harder to debug and could impact query performance.

Released under the MIT License.