Skip to content

Block-Bodied Members ​

ExpressiveSharp supports block-bodied properties and methods decorated with [Expressive], in addition to expression-bodied members (=>).

Opt-In Feature

Block-bodied member support requires explicit opt-in. Set AllowBlockBody = true on the attribute or enable it globally via an MSBuild property. Without this, block bodies produce diagnostic EXP0004.

Why Block Bodies? ​

Expression-bodied members are concise but can become difficult to read when the logic involves complex conditionals:

db
    .Orders
    .Select(o => new { o.Id, Category = o.GetCategory() })

// Setup
public static class OrderExt
{
    // Hard to read as a nested ternary
    [Expressive]
    public static string GetCategoryTerse(this Order o) =>
        o.Items.Sum(i => i.Quantity) * 10 > 100 ? "Bulk" : "Regular";

    // Much clearer as a block body
    [Expressive(AllowBlockBody = true)]
    public static string GetCategory(this Order o)
    {
        var threshold = o.Items.Sum(i => i.Quantity) * 10;
        if (threshold > 100) return "Bulk";
        return "Regular";
    }
}
SELECT "o"."Id", CASE
    WHEN (
        SELECT COALESCE(SUM("l"."Quantity"), 0)
        FROM "LineItems" AS "l"
        WHERE "o"."Id" = "l"."OrderId") * 10 > 100 THEN 'Bulk'
    ELSE 'Regular'
END AS "Category"
FROM "Orders" AS "o"
SELECT o."Id", CASE
    WHEN (
        SELECT COALESCE(sum(l."Quantity"), 0)::int
        FROM "LineItems" AS l
        WHERE o."Id" = l."OrderId") * 10 > 100 THEN 'Bulk'
    ELSE 'Regular'
END AS "Category"
FROM "Orders" AS o
SELECT [o].[Id], CASE
    WHEN (
        SELECT COALESCE(SUM([l].[Quantity]), 0)
        FROM [LineItems] AS [l]
        WHERE [o].[Id] = [l].[OrderId]) * 10 > 100 THEN N'Bulk'
    ELSE N'Regular'
END AS [Category]
FROM [Orders] AS [o]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Category" : {
                 "$cond" : {
                     "if" : {
                         "$gt" : [
                            {
                                 "$multiply" : [
                                    { "$sum" : "$Items.Quantity" },
                                    10
                                ] 
                            },
                            100
                        ] 
                    },
                    "then" : "Bulk",
                    "else" : "Regular" 
                } 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.GetCategoryTerse_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 
    {
        // // Hard to read as a nested ternary
        // [Expressive]
        // public static string GetCategoryTerse(this Order o) => o.Items.Sum(i => i.Quantity) * 10 > 100 ? "Bulk" : "Regular";
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>> GetCategoryTerse_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_4 = 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 p_i_5 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem), "i"); // i => i.Quantity
            var expr_6 = global::System.Linq.Expressions.Expression.Property(p_i_5, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("Quantity", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.Quantity
            var expr_7 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, int>>(expr_6, p_i_5);
            var expr_3 = global::System.Linq.Expressions.Expression.Call(global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::System.Linq.Enumerable).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static), m => m.Name == "Sum" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericType && !m.GetParameters()[1].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.GetGenericArguments()[1] == typeof(int))).MakeGenericMethod(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem)), new global::System.Linq.Expressions.Expression[] { expr_4, expr_7 });
            var expr_8 = global::System.Linq.Expressions.Expression.Constant(10, typeof(int)); // 10
            var expr_2 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Multiply, expr_3, expr_8);
            var expr_9 = global::System.Linq.Expressions.Expression.Constant(100, typeof(int)); // 100
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, expr_2, expr_9);
            var expr_10 = global::System.Linq.Expressions.Expression.Constant("Bulk", typeof(string)); // "Bulk"
            var expr_11 = global::System.Linq.Expressions.Expression.Constant("Regular", typeof(string)); // "Regular"
            var expr_0 = global::System.Linq.Expressions.Expression.Condition(expr_1, expr_10, expr_11, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>>(expr_0, p_o);
        }
    }
}


// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.GetCategory_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 
    {
        // // Much clearer as a block body
        // [Expressive(AllowBlockBody = true)]
        // public static string GetCategory(this Order o)
        // {
        //     var threshold = o.Items.Sum(i => i.Quantity) * 10;
        //     if (threshold > 100)
        //         return "Bulk";
        //     return "Regular";
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>> GetCategory_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.Variable(typeof(int), "threshold"); // {         var threshold = o.Items.Sum(i => i.Quantity) * ...
            var expr_3 = 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 p_i_4 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem), "i"); // i => i.Quantity
            var expr_5 = global::System.Linq.Expressions.Expression.Property(p_i_4, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("Quantity", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.Quantity
            var expr_6 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, int>>(expr_5, p_i_4);
            var expr_2 = global::System.Linq.Expressions.Expression.Call(global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::System.Linq.Enumerable).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static), m => m.Name == "Sum" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericType && !m.GetParameters()[1].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.GetGenericArguments()[1] == typeof(int))).MakeGenericMethod(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem)), new global::System.Linq.Expressions.Expression[] { expr_3, expr_6 });
            var expr_7 = global::System.Linq.Expressions.Expression.Constant(10, typeof(int)); // 10
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Multiply, expr_2, expr_7);
            var expr_8 = global::System.Linq.Expressions.Expression.Assign(expr_0, expr_1);
            var expr_11 = global::System.Linq.Expressions.Expression.Constant(100, typeof(int)); // 100
            var expr_10 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, expr_0, expr_11);
            var expr_12 = global::System.Linq.Expressions.Expression.Constant("Bulk", typeof(string)); // "Bulk"
            var expr_13 = global::System.Linq.Expressions.Expression.Constant("Regular", typeof(string)); // "Regular"
            var expr_9 = global::System.Linq.Expressions.Expression.Condition(expr_10, expr_12, expr_13, typeof(string));
            var expr_14 = global::System.Linq.Expressions.Expression.Block(new global::System.Linq.Expressions.ParameterExpression[] { expr_0 }, new global::System.Linq.Expressions.Expression[] { expr_8, expr_9 });
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>>(expr_14, 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("GetCategoryTerse", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "GetCategoryTerse_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_Order_Expression");
            Register(map, typeof(global::ExpressiveSharp.Docs.Playground.Snippet.OrderExt).GetMethod("GetCategory", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "GetCategory_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, "wBfULqHPeXaXomVk5X6ll38BAABfX1NuaXBwZXQuY3M=")]
        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, Category = o.GetCategory() }
            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("GetCategory", 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.GetCategory()
            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("Category") });
            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) { }
    }
}

Both forms generate equivalent expression trees and produce identical SQL when used with EF Core.

Enabling Block Bodies ​

Per-Member ​

Add AllowBlockBody = true to the [Expressive] attribute:

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

// Setup
public static class OrderExt
{
    [Expressive(AllowBlockBody = true)]
    public static string Tier(this Order o)
    {
        var total = o.Items.Sum(i => i.UnitPrice * i.Quantity);
        if (total >= 1000m) return "Premium";
        if (total >= 100m) return "Standard";
        return "Budget";
    }
}
SELECT "o"."Id", CASE
    WHEN ef_compare((
        SELECT COALESCE(ef_sum(ef_multiply("l"."UnitPrice", CAST("l"."Quantity" AS TEXT))), '0.0')
        FROM "LineItems" AS "l"
        WHERE "o"."Id" = "l"."OrderId"), '1000.0') >= 0 THEN 'Premium'
    WHEN ef_compare((
        SELECT COALESCE(ef_sum(ef_multiply("l0"."UnitPrice", CAST("l0"."Quantity" AS TEXT))), '0.0')
        FROM "LineItems" AS "l0"
        WHERE "o"."Id" = "l0"."OrderId"), '100.0') >= 0 THEN 'Standard'
    ELSE 'Budget'
END AS "Tier"
FROM "Orders" AS "o"
SELECT o."Id", CASE
    WHEN (
        SELECT COALESCE(sum(l."UnitPrice" * l."Quantity"::numeric(18,2)), 0.0)
        FROM "LineItems" AS l
        WHERE o."Id" = l."OrderId") >= 1000.0 THEN 'Premium'
    WHEN (
        SELECT COALESCE(sum(l0."UnitPrice" * l0."Quantity"::numeric(18,2)), 0.0)
        FROM "LineItems" AS l0
        WHERE o."Id" = l0."OrderId") >= 100.0 THEN 'Standard'
    ELSE 'Budget'
END AS "Tier"
FROM "Orders" AS o
SELECT [o].[Id], CASE
    WHEN (
        SELECT COALESCE(SUM([l].[UnitPrice] * CAST([l].[Quantity] AS decimal(18,2))), 0.0)
        FROM [LineItems] AS [l]
        WHERE [o].[Id] = [l].[OrderId]) >= 1000.0 THEN N'Premium'
    WHEN (
        SELECT COALESCE(SUM([l0].[UnitPrice] * CAST([l0].[Quantity] AS decimal(18,2))), 0.0)
        FROM [LineItems] AS [l0]
        WHERE [o].[Id] = [l0].[OrderId]) >= 100.0 THEN N'Standard'
    ELSE N'Budget'
END AS [Tier]
FROM [Orders] AS [o]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Tier" : {
                 "$cond" : {
                     "if" : {
                         "$gte" : [
                            {
                                 "$sum" : {
                                     "$map" : {
                                         "input" : "$Items",
                                        "as" : "i",
                                        "in" : {
                                             "$multiply" : ["$$i.UnitPrice", "$$i.Quantity"] 
                                        } 
                                    } 
                                } 
                            },
                            { "$numberDecimal" : "1000" }
                        ] 
                    },
                    "then" : "Premium",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$gte" : [
                                    {
                                         "$sum" : {
                                             "$map" : {
                                                 "input" : "$Items",
                                                "as" : "i",
                                                "in" : {
                                                     "$multiply" : ["$$i.UnitPrice", "$$i.Quantity"] 
                                                } 
                                            } 
                                        } 
                                    },
                                    { "$numberDecimal" : "100" }
                                ] 
                            },
                            "then" : "Standard",
                            "else" : "Budget" 
                        } 
                    } 
                } 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.Tier_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(AllowBlockBody = true)]
        // public static string Tier(this Order o)
        // {
        //     var total = o.Items.Sum(i => i.UnitPrice * i.Quantity);
        //     if (total >= 1000m)
        //         return "Premium";
        //     if (total >= 100m)
        //         return "Standard";
        //     return "Budget";
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>> Tier_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.Variable(typeof(decimal), "total"); // {         var total = o.Items.Sum(i => i.UnitPrice * i.Qu...
            var expr_2 = 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 p_i_3 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem), "i"); // i => i.UnitPrice * i.Quantity
            var expr_5 = global::System.Linq.Expressions.Expression.Property(p_i_3, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("UnitPrice", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.UnitPrice
            var expr_7 = global::System.Linq.Expressions.Expression.Property(p_i_3, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("Quantity", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.Quantity
            var expr_6 = global::System.Linq.Expressions.Expression.Convert(expr_7, typeof(decimal));
            var expr_4 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Multiply, expr_5, expr_6);
            var expr_8 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, decimal>>(expr_4, p_i_3);
            var expr_1 = global::System.Linq.Expressions.Expression.Call(global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::System.Linq.Enumerable).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static), m => m.Name == "Sum" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericType && !m.GetParameters()[1].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.GetGenericArguments()[1] == typeof(decimal))).MakeGenericMethod(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem)), new global::System.Linq.Expressions.Expression[] { expr_2, expr_8 });
            var expr_9 = global::System.Linq.Expressions.Expression.Assign(expr_0, expr_1);
            var expr_12 = global::System.Linq.Expressions.Expression.Constant(1000m, typeof(decimal)); // 1000m
            var expr_11 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_12);
            var expr_13 = global::System.Linq.Expressions.Expression.Constant("Premium", typeof(string)); // "Premium"
            var expr_16 = global::System.Linq.Expressions.Expression.Constant(100m, typeof(decimal)); // 100m
            var expr_15 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_0, expr_16);
            var expr_17 = global::System.Linq.Expressions.Expression.Constant("Standard", typeof(string)); // "Standard"
            var expr_18 = global::System.Linq.Expressions.Expression.Constant("Budget", typeof(string)); // "Budget"
            var expr_14 = global::System.Linq.Expressions.Expression.Condition(expr_15, expr_17, expr_18, typeof(string));
            var expr_10 = global::System.Linq.Expressions.Expression.Condition(expr_11, expr_13, expr_14, typeof(string));
            var expr_19 = global::System.Linq.Expressions.Expression.Block(new global::System.Linq.Expressions.ParameterExpression[] { expr_0 }, new global::System.Linq.Expressions.Expression[] { expr_9, expr_10 });
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>>(expr_19, 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("Tier", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "Tier_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, "EoDgc8CZ1eMx2Avrf8hWXX8BAABfX1NuaXBwZXQuY3M=")]
        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, Tier = o.Tier() }
            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("Tier", 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.Tier()
            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("Tier") });
            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) { }
    }
}

Globally via MSBuild ​

Enable block bodies for all [Expressive] members in a project by adding the Expressive_AllowBlockBody property:

xml
<PropertyGroup>
    <Expressive_AllowBlockBody>true</Expressive_AllowBlockBody>
</PropertyGroup>

This is equivalent to setting AllowBlockBody = true on every [Expressive] member in the project.

Supported Constructs ​

Return Statements ​

Simple return statements are the most basic block body form:

db
    .Orders
    .Select(o => new { o.Id, Constant = o.GetConstant() })

// Setup
public static class OrderExt
{
    [Expressive(AllowBlockBody = true)]
    public static int GetConstant(this Order o)
    {
        return 42;
    }
}
SELECT "o"."Id", 42 AS "Constant"
FROM "Orders" AS "o"
SELECT o."Id", 42 AS "Constant"
FROM "Orders" AS o
SELECT [o].[Id], 42 AS [Constant]
FROM [Orders] AS [o]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Constant" : { "$literal" : 42 } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.GetConstant_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(AllowBlockBody = true)]
        // public static int GetConstant(this Order o)
        // {
        //     return 42;
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int>> GetConstant_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(42, typeof(int)); // 42
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, int>>(expr_0, 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("GetConstant", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "GetConstant_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, "PJJ7wr3ZQ4qz8XG+TMNz838BAABfX1NuaXBwZXQuY3M=")]
        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, Constant = o.GetConstant() }
            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("GetConstant", 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.GetConstant()
            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("Constant") });
            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) { }
    }
}

If/Else Statements ​

If/else chains are converted to nested Expression.Condition (ternary) nodes:

db
    .Products
    .Select(p => new { p.Name, Category = p.GetCategory() })

// Setup
public static class ProductExt
{
    [Expressive(AllowBlockBody = true)]
    public static string GetCategory(this Product p)
    {
        if (p.ListPrice >= 100)
            return "Premium";
        else if (p.ListPrice >= 50)
            return "Standard";
        else
            return "Budget";
    }
}
SELECT "p"."Name", CASE
    WHEN ef_compare("p"."ListPrice", '100.0') >= 0 THEN 'Premium'
    WHEN ef_compare("p"."ListPrice", '50.0') >= 0 THEN 'Standard'
    ELSE 'Budget'
END AS "Category"
FROM "Products" AS "p"
SELECT p."Name", CASE
    WHEN p."ListPrice" >= 100.0 THEN 'Premium'
    WHEN p."ListPrice" >= 50.0 THEN 'Standard'
    ELSE 'Budget'
END AS "Category"
FROM "Products" AS p
SELECT [p].[Name], CASE
    WHEN [p].[ListPrice] >= 100.0 THEN N'Premium'
    WHEN [p].[ListPrice] >= 50.0 THEN N'Standard'
    ELSE N'Budget'
END AS [Category]
FROM [Products] AS [p]
playground.products.Aggregate([
    {
         "$project" : {
             "Name" : "$Name",
            "Category" : {
                 "$cond" : {
                     "if" : {
                         "$gte" : [
                            "$ListPrice",
                            { "$numberDecimal" : "100" }
                        ] 
                    },
                    "then" : "Premium",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$gte" : [
                                    "$ListPrice",
                                    { "$numberDecimal" : "50" }
                                ] 
                            },
                            "then" : "Standard",
                            "else" : "Budget" 
                        } 
                    } 
                } 
            },
            "_id" : 0 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.GetCategory_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(AllowBlockBody = true)]
        // public static string GetCategory(this Product p)
        // {
        //     if (p.ListPrice >= 100)
        //         return "Premium";
        //     else if (p.ListPrice >= 50)
        //         return "Standard";
        //     else
        //         return "Budget";
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>> GetCategory_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_2 = 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_4 = global::System.Linq.Expressions.Expression.Constant(100, typeof(int)); // 100
            var expr_3 = global::System.Linq.Expressions.Expression.Convert(expr_4, typeof(decimal));
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_2, expr_3);
            var expr_5 = global::System.Linq.Expressions.Expression.Constant("Premium", typeof(string)); // "Premium"
            var expr_8 = 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_10 = global::System.Linq.Expressions.Expression.Constant(50, typeof(int)); // 50
            var expr_9 = global::System.Linq.Expressions.Expression.Convert(expr_10, typeof(decimal));
            var expr_7 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThanOrEqual, expr_8, expr_9);
            var expr_11 = global::System.Linq.Expressions.Expression.Constant("Standard", typeof(string)); // "Standard"
            var expr_12 = global::System.Linq.Expressions.Expression.Constant("Budget", typeof(string)); // "Budget"
            var expr_6 = global::System.Linq.Expressions.Expression.Condition(expr_7, expr_11, expr_12, typeof(string));
            var expr_0 = global::System.Linq.Expressions.Expression.Condition(expr_1, expr_5, expr_6, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>>(expr_0, 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("GetCategory", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_ProductExt", "GetCategory_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, "lipRjIX11eNRinPE6CSYO4EBAABfX1NuaXBwZXQuY3M=")]
        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, Category = p.GetCategory() }
            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("GetCategory", 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.GetCategory()
            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("Category") });
            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) { }
    }
}

An if without an else is supported when followed by a fallback return:

db
    .Orders
    .Select(o => new { o.Id, Status = o.GetStatus() })

// Setup
public static class OrderExt
{
    [Expressive(AllowBlockBody = true)]
    public static string GetStatus(this Order o)
    {
        if (o.Status == OrderStatus.Paid)
            return "Active";
        return "Inactive";  // Fallback
    }
}
.param set @Paid 1

SELECT "o"."Id", CASE
    WHEN "o"."Status" = @Paid THEN 'Active'
    ELSE 'Inactive'
END AS "Status"
FROM "Orders" AS "o"
-- @Paid='1'
SELECT o."Id", CASE
    WHEN o."Status" = @Paid THEN 'Active'
    ELSE 'Inactive'
END AS "Status"
FROM "Orders" AS o
DECLARE @Paid int = 1;

SELECT [o].[Id], CASE
    WHEN [o].[Status] = @Paid THEN N'Active'
    ELSE N'Inactive'
END AS [Status]
FROM [Orders] AS [o]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Status" : {
                 "$cond" : {
                     "if" : {
                         "$eq" : ["$Status", 1] 
                    },
                    "then" : "Active",
                    "else" : "Inactive" 
                } 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.GetStatus_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(AllowBlockBody = true)]
        // public static string GetStatus(this Order o)
        // {
        //     if (o.Status == OrderStatus.Paid)
        //         return "Active";
        //     return "Inactive"; // Fallback
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>> GetStatus_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_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)); // o.Status
            var expr_3 = 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)); // OrderStatus.Paid
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Equal, expr_2, expr_3);
            var expr_4 = global::System.Linq.Expressions.Expression.Constant("Active", typeof(string)); // "Active"
            var expr_5 = global::System.Linq.Expressions.Expression.Constant("Inactive", typeof(string)); // "Inactive"
            var expr_0 = global::System.Linq.Expressions.Expression.Condition(expr_1, expr_4, expr_5, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>>(expr_0, 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("GetStatus", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "GetStatus_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, "mGEGMBVOyr4FGW7nFnAVG38BAABfX1NuaXBwZXQuY3M=")]
        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, Status = o.GetStatus() }
            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("GetStatus", 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.GetStatus()
            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("Status") });
            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) { }
    }
}

Multiple independent early-return statements are converted to a nested ternary chain:

db
    .Products
    .Select(p => new { p.Name, Range = p.GetPriceRange() })

// Setup
public static class ProductExt
{
    [Expressive(AllowBlockBody = true)]
    public static string GetPriceRange(this Product p)
    {
        if (p.ListPrice > 1000) return "Very High";
        if (p.ListPrice > 100)  return "High";
        if (p.ListPrice > 10)   return "Medium";
        return "Low";
    }
}
SELECT "p"."Name", CASE
    WHEN ef_compare("p"."ListPrice", '1000.0') > 0 THEN 'Very High'
    WHEN ef_compare("p"."ListPrice", '100.0') > 0 THEN 'High'
    WHEN ef_compare("p"."ListPrice", '10.0') > 0 THEN 'Medium'
    ELSE 'Low'
END AS "Range"
FROM "Products" AS "p"
SELECT p."Name", CASE
    WHEN p."ListPrice" > 1000.0 THEN 'Very High'
    WHEN p."ListPrice" > 100.0 THEN 'High'
    WHEN p."ListPrice" > 10.0 THEN 'Medium'
    ELSE 'Low'
END AS "Range"
FROM "Products" AS p
SELECT [p].[Name], CASE
    WHEN [p].[ListPrice] > 1000.0 THEN N'Very High'
    WHEN [p].[ListPrice] > 100.0 THEN N'High'
    WHEN [p].[ListPrice] > 10.0 THEN N'Medium'
    ELSE N'Low'
END AS [Range]
FROM [Products] AS [p]
playground.products.Aggregate([
    {
         "$project" : {
             "Name" : "$Name",
            "Range" : {
                 "$cond" : {
                     "if" : {
                         "$gt" : [
                            "$ListPrice",
                            { "$numberDecimal" : "1000" }
                        ] 
                    },
                    "then" : "Very High",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$gt" : [
                                    "$ListPrice",
                                    { "$numberDecimal" : "100" }
                                ] 
                            },
                            "then" : "High",
                            "else" : {
                                 "$cond" : {
                                     "if" : {
                                         "$gt" : [
                                            "$ListPrice",
                                            { "$numberDecimal" : "10" }
                                        ] 
                                    },
                                    "then" : "Medium",
                                    "else" : "Low" 
                                } 
                            } 
                        } 
                    } 
                } 
            },
            "_id" : 0 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_ProductExt.GetPriceRange_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(AllowBlockBody = true)]
        // public static string GetPriceRange(this Product p)
        // {
        //     if (p.ListPrice > 1000)
        //         return "Very High";
        //     if (p.ListPrice > 100)
        //         return "High";
        //     if (p.ListPrice > 10)
        //         return "Medium";
        //     return "Low";
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>> GetPriceRange_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_2 = 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_4 = global::System.Linq.Expressions.Expression.Constant(1000, typeof(int)); // 1000
            var expr_3 = global::System.Linq.Expressions.Expression.Convert(expr_4, typeof(decimal));
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, expr_2, expr_3);
            var expr_5 = global::System.Linq.Expressions.Expression.Constant("Very High", typeof(string)); // "Very High"
            var expr_8 = 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_10 = global::System.Linq.Expressions.Expression.Constant(100, typeof(int)); // 100
            var expr_9 = global::System.Linq.Expressions.Expression.Convert(expr_10, typeof(decimal));
            var expr_7 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, expr_8, expr_9);
            var expr_11 = global::System.Linq.Expressions.Expression.Constant("High", typeof(string)); // "High"
            var expr_14 = 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_16 = global::System.Linq.Expressions.Expression.Constant(10, typeof(int)); // 10
            var expr_15 = global::System.Linq.Expressions.Expression.Convert(expr_16, typeof(decimal));
            var expr_13 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, expr_14, expr_15);
            var expr_17 = global::System.Linq.Expressions.Expression.Constant("Medium", typeof(string)); // "Medium"
            var expr_18 = global::System.Linq.Expressions.Expression.Constant("Low", typeof(string)); // "Low"
            var expr_12 = global::System.Linq.Expressions.Expression.Condition(expr_13, expr_17, expr_18, typeof(string));
            var expr_6 = global::System.Linq.Expressions.Expression.Condition(expr_7, expr_11, expr_12, typeof(string));
            var expr_0 = global::System.Linq.Expressions.Expression.Condition(expr_1, expr_5, expr_6, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>>(expr_0, 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("GetPriceRange", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_ProductExt", "GetPriceRange_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, "lpDQLg3AMTM9B4NBEwdFnoEBAABfX1NuaXBwZXQuY3M=")]
        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, Range = p.GetPriceRange() }
            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("GetPriceRange", 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.GetPriceRange()
            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("Range") });
            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) { }
    }
}

Switch Statements ​

Switch statements are converted to nested conditional expressions:

db
    .Orders
    .Select(o => new { o.Id, Label = o.GetLabel() })

// Setup
public static class OrderExt
{
    [Expressive(AllowBlockBody = true)]
    public static string GetLabel(this Order o)
    {
        switch (o.Status)
        {
            case OrderStatus.Pending: return "New";
            case OrderStatus.Paid: return "Active";
            case OrderStatus.Delivered: return "Closed";
            default: return "Unknown";
        }
    }
}
.param set @Pending 0
.param set @Paid 1
.param set @Delivered 3

SELECT "o"."Id", CASE
    WHEN "o"."Status" = @Pending THEN 'New'
    WHEN "o"."Status" = @Paid THEN 'Active'
    WHEN "o"."Status" = @Delivered THEN 'Closed'
    ELSE 'Unknown'
END AS "Label"
FROM "Orders" AS "o"
-- @Pending='0'
-- @Paid='1'
-- @Delivered='3'
SELECT o."Id", CASE
    WHEN o."Status" = @Pending THEN 'New'
    WHEN o."Status" = @Paid THEN 'Active'
    WHEN o."Status" = @Delivered THEN 'Closed'
    ELSE 'Unknown'
END AS "Label"
FROM "Orders" AS o
DECLARE @Pending int = 0;
DECLARE @Paid int = 1;
DECLARE @Delivered int = 3;

SELECT [o].[Id], CASE
    WHEN [o].[Status] = @Pending THEN N'New'
    WHEN [o].[Status] = @Paid THEN N'Active'
    WHEN [o].[Status] = @Delivered THEN N'Closed'
    ELSE N'Unknown'
END AS [Label]
FROM [Orders] AS [o]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Label" : {
                 "$cond" : {
                     "if" : {
                         "$eq" : ["$Status", 0] 
                    },
                    "then" : "New",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$eq" : ["$Status", 1] 
                            },
                            "then" : "Active",
                            "else" : {
                                 "$cond" : {
                                     "if" : {
                                         "$eq" : ["$Status", 3] 
                                    },
                                    "then" : "Closed",
                                    "else" : "Unknown" 
                                } 
                            } 
                        } 
                    } 
                } 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.GetLabel_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(AllowBlockBody = true)]
        // public static string GetLabel(this Order o)
        // {
        //     switch (o.Status)
        //     {
        //         case OrderStatus.Pending:
        //             return "New";
        //         case OrderStatus.Paid:
        //             return "Active";
        //         case OrderStatus.Delivered:
        //             return "Closed";
        //         default:
        //             return "Unknown";
        //     }
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>> GetLabel_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.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)); // o.Status
            var expr_1 = global::System.Linq.Expressions.Expression.Constant("New", typeof(string)); // "New"
            var expr_2 = global::System.Linq.Expressions.Expression.Field(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.OrderStatus).GetField("Pending", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static)); // OrderStatus.Pending
            var expr_3 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_2);
            var expr_4 = global::System.Linq.Expressions.Expression.Constant("Active", typeof(string)); // "Active"
            var expr_5 = 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)); // OrderStatus.Paid
            var expr_6 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_5);
            var expr_7 = global::System.Linq.Expressions.Expression.Constant("Closed", typeof(string)); // "Closed"
            var expr_8 = global::System.Linq.Expressions.Expression.Field(null, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.OrderStatus).GetField("Delivered", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static)); // OrderStatus.Delivered
            var expr_9 = global::System.Linq.Expressions.Expression.Equal(expr_0, expr_8);
            var expr_10 = global::System.Linq.Expressions.Expression.Constant("Unknown", typeof(string)); // "Unknown"
            var expr_11 = global::System.Linq.Expressions.Expression.Condition(expr_9, expr_7, expr_10, typeof(string));
            var expr_12 = global::System.Linq.Expressions.Expression.Condition(expr_6, expr_4, expr_11, typeof(string));
            var expr_13 = global::System.Linq.Expressions.Expression.Condition(expr_3, expr_1, expr_12, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>>(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("GetLabel", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "GetLabel_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, "duNEC9SIJjxexcmWjS3ft38BAABfX1NuaXBwZXQuY3M=")]
        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, Label = o.GetLabel() }
            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("GetLabel", 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.GetLabel()
            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("Label") });
            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) { }
    }
}

Local Variable Declarations ​

Local variables declared at the method body level are emitted as Expression.Variable nodes within an Expression.Block:

db
    .LineItems
    .Select(i => new { i.Id, Doubled = i.CalculateDouble() })

// Setup
public static class LineItemExt
{
    [Expressive(AllowBlockBody = true)]
    public static decimal CalculateDouble(this LineItem i)
    {
        var doubled = i.UnitPrice * 2;
        return doubled + 5;
    }
}
SELECT "l"."Id", ef_add(ef_multiply("l"."UnitPrice", '2.0'), '5.0') AS "Doubled"
FROM "LineItems" AS "l"
SELECT l."Id", l."UnitPrice" * 2.0 + 5.0 AS "Doubled"
FROM "LineItems" AS l
SELECT [l].[Id], [l].[UnitPrice] * 2.0 + 5.0 AS [Doubled]
FROM [LineItems] AS [l]
playground.line_items.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Doubled" : {
                 "$add" : [
                    {
                         "$multiply" : [
                            "$UnitPrice",
                            { "$numberDecimal" : "2" }
                        ] 
                    },
                    { "$numberDecimal" : "5" }
                ] 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_LineItemExt.CalculateDouble_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_LineItem.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_LineItemExt 
    {
        // [Expressive(AllowBlockBody = true)]
        // public static decimal CalculateDouble(this LineItem i)
        // {
        //     var doubled = i.UnitPrice * 2;
        //     return doubled + 5;
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, decimal>> CalculateDouble_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_LineItem_Expression() 
        {
            var p_i = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem), "i");
            var expr_0 = global::System.Linq.Expressions.Expression.Variable(typeof(decimal), "doubled"); // {         var doubled = i.UnitPrice * 2;         return d...
            var expr_2 = global::System.Linq.Expressions.Expression.Property(p_i, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("UnitPrice", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.UnitPrice
            var expr_4 = global::System.Linq.Expressions.Expression.Constant(2, typeof(int)); // 2
            var expr_3 = global::System.Linq.Expressions.Expression.Convert(expr_4, typeof(decimal));
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Multiply, expr_2, expr_3);
            var expr_5 = global::System.Linq.Expressions.Expression.Assign(expr_0, expr_1);
            var expr_8 = global::System.Linq.Expressions.Expression.Constant(5, typeof(int)); // 5
            var expr_7 = global::System.Linq.Expressions.Expression.Convert(expr_8, typeof(decimal));
            var expr_6 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Add, expr_0, expr_7);
            var expr_9 = global::System.Linq.Expressions.Expression.Block(new global::System.Linq.Expressions.ParameterExpression[] { expr_0 }, new global::System.Linq.Expressions.Expression[] { expr_5, expr_6 });
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, decimal>>(expr_9, p_i);
        }
    }
}


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

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


// === 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.LineItemExt).GetMethod("CalculateDouble", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_LineItemExt", "CalculateDouble_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_LineItem_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, "pDWI+IhwV4kwpy58sPPA0YIBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<T1> __Polyfill_Select_3e61_14_24<T0, T1>(
            this global::ExpressiveSharp.IExpressiveQueryable<T0> source,
            global::System.Func<T0, T1> __func)
        {
            // Source: i => new { i.Id, Doubled = i.CalculateDouble() }
            var i3e6114c24_p_i = global::System.Linq.Expressions.Expression.Parameter(typeof(T0), "i");
            var i3e6114c24_expr_1 = global::System.Linq.Expressions.Expression.Property(i3e6114c24_p_i, typeof(T0).GetProperty("Id", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.Id
            var i3e6114c24_expr_2 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.LineItemExt).GetMethod("CalculateDouble", 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[] { i3e6114c24_p_i }); // i.CalculateDouble()
            var i3e6114c24_expr_3 = typeof(T1).GetConstructors()[0];
            var i3e6114c24_expr_0 = global::System.Linq.Expressions.Expression.New(i3e6114c24_expr_3, new global::System.Linq.Expressions.Expression[] { i3e6114c24_expr_1, i3e6114c24_expr_2 }, new global::System.Reflection.MemberInfo[] { typeof(T1).GetProperty("Id"), typeof(T1).GetProperty("Doubled") });
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<T0, T1>>(i3e6114c24_expr_0, i3e6114c24_p_i);
            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) { }
    }
}

Transitive references are supported:

db
    .LineItems
    .Select(i => new { i.Id, Complex = i.CalculateComplex() })

// Setup
public static class LineItemExt
{
    [Expressive(AllowBlockBody = true)]
    public static decimal CalculateComplex(this LineItem i)
    {
        var a = i.UnitPrice * 2;
        var b = a + 5;
        return b + 10;
    }
}
SELECT "l"."Id", ef_add(ef_add(ef_multiply("l"."UnitPrice", '2.0'), '5.0'), '10.0') AS "Complex"
FROM "LineItems" AS "l"
SELECT l."Id", l."UnitPrice" * 2.0 + 5.0 + 10.0 AS "Complex"
FROM "LineItems" AS l
SELECT [l].[Id], [l].[UnitPrice] * 2.0 + 5.0 + 10.0 AS [Complex]
FROM [LineItems] AS [l]
playground.line_items.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Complex" : {
                 "$add" : [
                    {
                         "$multiply" : [
                            "$UnitPrice",
                            { "$numberDecimal" : "2" }
                        ] 
                    },
                    { "$numberDecimal" : "5" },
                    { "$numberDecimal" : "10" }
                ] 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_LineItemExt.CalculateComplex_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_LineItem.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_LineItemExt 
    {
        // [Expressive(AllowBlockBody = true)]
        // public static decimal CalculateComplex(this LineItem i)
        // {
        //     var a = i.UnitPrice * 2;
        //     var b = a + 5;
        //     return b + 10;
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, decimal>> CalculateComplex_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_LineItem_Expression() 
        {
            var p_i = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem), "i");
            var expr_0 = global::System.Linq.Expressions.Expression.Variable(typeof(decimal), "a"); // {         var a = i.UnitPrice * 2;         var b = a + 5;...
            var expr_2 = global::System.Linq.Expressions.Expression.Property(p_i, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("UnitPrice", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.UnitPrice
            var expr_4 = global::System.Linq.Expressions.Expression.Constant(2, typeof(int)); // 2
            var expr_3 = global::System.Linq.Expressions.Expression.Convert(expr_4, typeof(decimal));
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Multiply, expr_2, expr_3);
            var expr_5 = global::System.Linq.Expressions.Expression.Assign(expr_0, expr_1);
            var expr_6 = global::System.Linq.Expressions.Expression.Variable(typeof(decimal), "b");
            var expr_9 = global::System.Linq.Expressions.Expression.Constant(5, typeof(int)); // 5
            var expr_8 = global::System.Linq.Expressions.Expression.Convert(expr_9, typeof(decimal));
            var expr_7 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Add, expr_0, expr_8);
            var expr_10 = global::System.Linq.Expressions.Expression.Assign(expr_6, expr_7);
            var expr_13 = global::System.Linq.Expressions.Expression.Constant(10, typeof(int)); // 10
            var expr_12 = global::System.Linq.Expressions.Expression.Convert(expr_13, typeof(decimal));
            var expr_11 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Add, expr_6, expr_12);
            var expr_14 = global::System.Linq.Expressions.Expression.Block(new global::System.Linq.Expressions.ParameterExpression[] { expr_0, expr_6 }, new global::System.Linq.Expressions.Expression[] { expr_5, expr_10, expr_11 });
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, decimal>>(expr_14, p_i);
        }
    }
}


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

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


// === 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.LineItemExt).GetMethod("CalculateComplex", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_LineItemExt", "CalculateComplex_P0_ExpressiveSharp_Docs_PlaygroundModel_Webshop_LineItem_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, "NEkfbUl1sMDFFayd/B8zA4IBAABfX1NuaXBwZXQuY3M=")]
        internal static global::ExpressiveSharp.IExpressiveQueryable<T1> __Polyfill_Select_3e61_14_24<T0, T1>(
            this global::ExpressiveSharp.IExpressiveQueryable<T0> source,
            global::System.Func<T0, T1> __func)
        {
            // Source: i => new { i.Id, Complex = i.CalculateComplex() }
            var i3e6114c24_p_i = global::System.Linq.Expressions.Expression.Parameter(typeof(T0), "i");
            var i3e6114c24_expr_1 = global::System.Linq.Expressions.Expression.Property(i3e6114c24_p_i, typeof(T0).GetProperty("Id", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.Id
            var i3e6114c24_expr_2 = global::System.Linq.Expressions.Expression.Call(typeof(global::ExpressiveSharp.Docs.Playground.Snippet.LineItemExt).GetMethod("CalculateComplex", 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[] { i3e6114c24_p_i }); // i.CalculateComplex()
            var i3e6114c24_expr_3 = typeof(T1).GetConstructors()[0];
            var i3e6114c24_expr_0 = global::System.Linq.Expressions.Expression.New(i3e6114c24_expr_3, new global::System.Linq.Expressions.Expression[] { i3e6114c24_expr_1, i3e6114c24_expr_2 }, new global::System.Reflection.MemberInfo[] { typeof(T1).GetProperty("Id"), typeof(T1).GetProperty("Complex") });
            var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<T0, T1>>(i3e6114c24_expr_0, i3e6114c24_p_i);
            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) { }
    }
}

Variable Duplication Caveat

The FlattenBlockExpressions transformer (applied by UseExpressives() in EF Core) inlines local variables at each usage point. If a variable is referenced multiple times, its initializer is duplicated:

csharp
[Expressive(AllowBlockBody = true)]
public static decimal Foo(this LineItem i)
{
    var x = i.UnitPrice * i.Quantity;
    return x + x;
    // After FlattenBlockExpressions: (UnitPrice * Quantity) + (UnitPrice * Quantity)
}

For pure expressions (no side effects), this is semantically identical. The generator detects potential side effects and reports EXP0005.


Foreach Loops ​

foreach loops are emitted as Expression.Loop with the enumerator pattern (GetEnumerator/MoveNext/Current). The ConvertLoopsToLinq transformer then rewrites these to equivalent LINQ method calls for providers like EF Core that cannot translate loop expressions:

db
    .Orders
    .Select(o => new { o.Id, Total = o.GetTotalLineItemPrice() })

// Setup
public static class OrderExt
{
    [Expressive(AllowBlockBody = true)]
    public static decimal GetTotalLineItemPrice(this Order o)
    {
        var total = 0m;
        foreach (var item in o.Items)
            total += item.UnitPrice;
        return total;
    }
}
SELECT "o"."Id", (
    SELECT COALESCE(ef_sum("l"."UnitPrice"), '0.0')
    FROM "LineItems" AS "l"
    WHERE "o"."Id" = "l"."OrderId") AS "Total"
FROM "Orders" AS "o"
SELECT o."Id", (
    SELECT COALESCE(sum(l."UnitPrice"), 0.0)
    FROM "LineItems" AS l
    WHERE o."Id" = l."OrderId") AS "Total"
FROM "Orders" AS o
SELECT [o].[Id], (
    SELECT COALESCE(SUM([l].[UnitPrice]), 0.0)
    FROM [LineItems] AS [l]
    WHERE [o].[Id] = [l].[OrderId]) AS [Total]
FROM [Orders] AS [o]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Total" : { "$sum" : "$Items.UnitPrice" } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.GetTotalLineItemPrice_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(AllowBlockBody = true)]
        // public static decimal GetTotalLineItemPrice(this Order o)
        // {
        //     var total = 0m;
        //     foreach (var item in o.Items)
        //         total += item.UnitPrice;
        //     return total;
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, decimal>> GetTotalLineItemPrice_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.Variable(typeof(decimal), "total"); // {         var total = 0m;         foreach (var item in o....
            var expr_1 = global::System.Linq.Expressions.Expression.Constant(0m, typeof(decimal)); // 0m
            var expr_2 = global::System.Linq.Expressions.Expression.Assign(expr_0, expr_1);
            var expr_4 = 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_5 = global::System.Linq.Expressions.Expression.Variable(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem), "item");
            var expr_6 = global::System.Linq.Expressions.Expression.Variable(typeof(global::System.Collections.Generic.IEnumerator<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>), "enumerator");
            var expr_7 = global::System.Linq.Expressions.Expression.Call(expr_4, typeof(global::System.Collections.Generic.IEnumerable<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>).GetMethod("GetEnumerator", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, new global::System.Type[] {  }, null));
            var expr_8 = global::System.Linq.Expressions.Expression.Assign(expr_6, expr_7);
            var expr_9 = global::System.Linq.Expressions.Expression.Label("break");
            var expr_10 = global::System.Linq.Expressions.Expression.Property(expr_6, typeof(global::System.Collections.Generic.IEnumerator<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem>).GetProperty("Current", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance));
            var expr_11 = global::System.Linq.Expressions.Expression.Assign(expr_5, expr_10);
            var expr_13 = global::System.Linq.Expressions.Expression.Property(expr_5, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("UnitPrice", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // item.UnitPrice
            var expr_14 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Add, expr_0, expr_13);
            var expr_12 = global::System.Linq.Expressions.Expression.Assign(expr_0, expr_14);
            var expr_15 = global::System.Linq.Expressions.Expression.Block(expr_11, expr_12);
            var expr_16 = global::System.Linq.Expressions.Expression.Call(expr_6, typeof(global::System.Collections.IEnumerator).GetMethod("MoveNext", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, new global::System.Type[] {  }, null));
            var expr_17 = global::System.Linq.Expressions.Expression.Break(expr_9);
            var expr_18 = global::System.Linq.Expressions.Expression.IfThenElse(expr_16, expr_15, expr_17);
            var expr_19 = global::System.Linq.Expressions.Expression.Loop(expr_18, expr_9);
            var expr_3 = global::System.Linq.Expressions.Expression.Block(new global::System.Linq.Expressions.ParameterExpression[] { expr_6, expr_5 }, expr_8, expr_19);
            var expr_20 = global::System.Linq.Expressions.Expression.Block(new global::System.Linq.Expressions.ParameterExpression[] { expr_0 }, new global::System.Linq.Expressions.Expression[] { expr_2, expr_3, expr_0 });
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, decimal>>(expr_20, 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("GetTotalLineItemPrice", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "GetTotalLineItemPrice_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, "sQhc5OqCnntobfRU2W+idn8BAABfX1NuaXBwZXQuY3M=")]
        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, Total = o.GetTotalLineItemPrice() }
            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("GetTotalLineItemPrice", 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.GetTotalLineItemPrice()
            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("Total") });
            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) { }
    }
}

After the ConvertLoopsToLinq transformer, this becomes equivalent to o.Items.Sum(item => item.UnitPrice).


For Loops ​

for loops over arrays or lists are emitted by the generator, but produce a EXP0006 warning recommending foreach for better LINQ provider compatibility:

csharp
[Expressive(AllowBlockBody = true)]
public int SumArray()
{
    var sum = 0;
    for (var i = 0; i < Items.Length; i++)
        sum += Items[i];
    return sum;
}

Unsupported Constructs ​

The following constructs are not supported in block bodies and produce diagnostics:

ConstructDiagnosticSeverityReason
while / do-while loopsEXP0006WarningNo reliable expression tree equivalent
try / catch / finallyEXP0006WarningNo expression tree equivalent
throw statementsEXP0006WarningNot reliably translatable by LINQ providers
async / awaitEXP0005ErrorSide effects incompatible with expression trees
Assignments (x = y)EXP0005ErrorSide effects in expression trees
++ / --EXP0005ErrorSide effects in expression trees

Use LINQ Instead of Loops

If you need aggregation logic, prefer LINQ methods in an expression-bodied member:

csharp
// Instead of a loop
public static class OrderExt
{
    [Expressive]
    public static decimal TotalPrice(this Order o) => o.Items.Sum(i => i.UnitPrice);
}

SQL Output Examples ​

If/Else to CASE WHEN ​

db
    .Orders
    .Select(o => new { o.Id, Category = o.GetCategoryFromThreshold() })

// Setup
public static class OrderExt
{
    [Expressive(AllowBlockBody = true)]
    public static string GetCategoryFromThreshold(this Order o)
    {
        var threshold = o.Items.Sum(i => i.Quantity) * 10;
        if (threshold > 100) return "Bulk";
        return "Regular";
    }
}
SELECT "o"."Id", CASE
    WHEN (
        SELECT COALESCE(SUM("l"."Quantity"), 0)
        FROM "LineItems" AS "l"
        WHERE "o"."Id" = "l"."OrderId") * 10 > 100 THEN 'Bulk'
    ELSE 'Regular'
END AS "Category"
FROM "Orders" AS "o"
SELECT o."Id", CASE
    WHEN (
        SELECT COALESCE(sum(l."Quantity"), 0)::int
        FROM "LineItems" AS l
        WHERE o."Id" = l."OrderId") * 10 > 100 THEN 'Bulk'
    ELSE 'Regular'
END AS "Category"
FROM "Orders" AS o
SELECT [o].[Id], CASE
    WHEN (
        SELECT COALESCE(SUM([l].[Quantity]), 0)
        FROM [LineItems] AS [l]
        WHERE [o].[Id] = [l].[OrderId]) * 10 > 100 THEN N'Bulk'
    ELSE N'Regular'
END AS [Category]
FROM [Orders] AS [o]
playground.orders.Aggregate([
    {
         "$project" : {
             "_id" : "$_id",
            "Category" : {
                 "$cond" : {
                     "if" : {
                         "$gt" : [
                            {
                                 "$multiply" : [
                                    { "$sum" : "$Items.Quantity" },
                                    10
                                ] 
                            },
                            100
                        ] 
                    },
                    "then" : "Bulk",
                    "else" : "Regular" 
                } 
            } 
        } 
    }
])
// === ExpressiveSharp_Docs_Playground_Snippet_OrderExt.GetCategoryFromThreshold_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(AllowBlockBody = true)]
        // public static string GetCategoryFromThreshold(this Order o)
        // {
        //     var threshold = o.Items.Sum(i => i.Quantity) * 10;
        //     if (threshold > 100)
        //         return "Bulk";
        //     return "Regular";
        // }
        static global::System.Linq.Expressions.Expression<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>> GetCategoryFromThreshold_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.Variable(typeof(int), "threshold"); // {         var threshold = o.Items.Sum(i => i.Quantity) * ...
            var expr_3 = 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 p_i_4 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem), "i"); // i => i.Quantity
            var expr_5 = global::System.Linq.Expressions.Expression.Property(p_i_4, typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem).GetProperty("Quantity", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // i.Quantity
            var expr_6 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem, int>>(expr_5, p_i_4);
            var expr_2 = global::System.Linq.Expressions.Expression.Call(global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::System.Linq.Enumerable).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static), m => m.Name == "Sum" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericType && !m.GetParameters()[1].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.GetGenericArguments()[1] == typeof(int))).MakeGenericMethod(typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.LineItem)), new global::System.Linq.Expressions.Expression[] { expr_3, expr_6 });
            var expr_7 = global::System.Linq.Expressions.Expression.Constant(10, typeof(int)); // 10
            var expr_1 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.Multiply, expr_2, expr_7);
            var expr_8 = global::System.Linq.Expressions.Expression.Assign(expr_0, expr_1);
            var expr_11 = global::System.Linq.Expressions.Expression.Constant(100, typeof(int)); // 100
            var expr_10 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, expr_0, expr_11);
            var expr_12 = global::System.Linq.Expressions.Expression.Constant("Bulk", typeof(string)); // "Bulk"
            var expr_13 = global::System.Linq.Expressions.Expression.Constant("Regular", typeof(string)); // "Regular"
            var expr_9 = global::System.Linq.Expressions.Expression.Condition(expr_10, expr_12, expr_13, typeof(string));
            var expr_14 = global::System.Linq.Expressions.Expression.Block(new global::System.Linq.Expressions.ParameterExpression[] { expr_0 }, new global::System.Linq.Expressions.Expression[] { expr_8, expr_9 });
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order, string>>(expr_14, 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("GetCategoryFromThreshold", allFlags, null, new global::System.Type[] { typeof(global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Order) }, null), "ExpressiveSharp.Generated.ExpressiveSharp_Docs_Playground_Snippet_OrderExt", "GetCategoryFromThreshold_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, "zYteK16vQ2PqsD2JdeF8DH8BAABfX1NuaXBwZXQuY3M=")]
        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, Category = o.GetCategoryFromThreshold() }
            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("GetCategoryFromThreshold", 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.GetCategoryFromThreshold()
            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("Category") });
            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) { }
    }
}

Switch Expression Equivalent ​

Block-body switch statements and expression-bodied switch expressions produce the same SQL:

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
    {
        >= 100m => "Premium",
        >= 50m  => "Standard",
        _       => "Budget",
    };
}
SELECT "p"."Name", CASE
    WHEN ef_compare("p"."ListPrice", '100.0') >= 0 THEN 'Premium'
    WHEN ef_compare("p"."ListPrice", '50.0') >= 0 THEN 'Standard'
    ELSE 'Budget'
END AS "Grade"
FROM "Products" AS "p"
SELECT p."Name", CASE
    WHEN p."ListPrice" >= 100.0 THEN 'Premium'
    WHEN p."ListPrice" >= 50.0 THEN 'Standard'
    ELSE 'Budget'
END AS "Grade"
FROM "Products" AS p
SELECT [p].[Name], CASE
    WHEN [p].[ListPrice] >= 100.0 THEN N'Premium'
    WHEN [p].[ListPrice] >= 50.0 THEN N'Standard'
    ELSE N'Budget'
END AS [Grade]
FROM [Products] AS [p]
playground.products.Aggregate([
    {
         "$project" : {
             "Name" : "$Name",
            "Grade" : {
                 "$cond" : {
                     "if" : {
                         "$gte" : [
                            "$ListPrice",
                            { "$numberDecimal" : "100" }
                        ] 
                    },
                    "then" : "Premium",
                    "else" : {
                         "$cond" : {
                             "if" : {
                                 "$gte" : [
                                    "$ListPrice",
                                    { "$numberDecimal" : "50" }
                                ] 
                            },
                            "then" : "Standard",
                            "else" : "Budget" 
                        } 
                    } 
                } 
            },
            "_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
        // {
        //     >= 100m => "Premium",
        //     >= 50m => "Standard",
        //     _ => "Budget",
        // };
        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("Budget", typeof(string)); // "Budget"
            var expr_3 = global::System.Linq.Expressions.Expression.Constant(50m, typeof(decimal)); // 50m
            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("Standard", typeof(string)); // "Standard"
            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("Premium", typeof(string)); // "Premium"
            var expr_9 = global::System.Linq.Expressions.Expression.Condition(expr_6, expr_8, expr_5, typeof(string));
            return global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::ExpressiveSharp.Docs.PlaygroundModel.Webshop.Product, string>>(expr_9, 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, "lauC5LYGkPS38aiHuxXaz4EBAABfX1NuaXBwZXQuY3M=")]
        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) { }
    }
}

Side Effect Detection ​

The source generator actively detects statements with side effects and reports diagnostics:

PatternDiagnostic
Property/field assignment (Bar = 10;)EXP0005 -- side effect detected
Compound assignment (Bar += 10;)EXP0005 -- side effect detected
Increment/decrement (Bar++;)EXP0005 -- side effect detected
Block body without AllowBlockBody = trueEXP0004 -- block body requires opt-in

See Limitations for the full list of restrictions.

Released under the MIT License.