DelegateDecompiler icon indicating copy to clipboard operation
DelegateDecompiler copied to clipboard

Feature request - Add an extension point to process expressions built at runtime within the DD process chain

Open magicmoux opened this issue 1 month ago • 6 comments

Hi @hazzik,

following on my last issue, I think it would be nice to provide an Extension point be able to include runtime built LINQ Extensions seamlessly into the DD pipeline.

So I POCed this fork's branch by adding a new [ExpressionFactory] attribute that allows you to define methods that generate expression trees dynamically at runtime during the decompilation phase. These custom operations integrate naturally into the LINQ query pipeline.

Direct usage and computed property patterns are demonstrated in the test group 91

Here's a quick overview of the design

Define an Expression Factory

Mark your factory method with [ExpressionFactory]:

[ExpressionFactory]
private static Expression BuildOrderBySequenceExpression<T, TKey>(
    Expression source, 
    Expression<Func<T, TKey>> keySelector, 
    IEnumerable<TKey> explicitSequence)
    where T : class
    where TKey : IEquatable<TKey>
{
    // Build expression tree dynamically based on runtime data
    // This is evaluated during query decompilation
}

Create the Public Extension Methods

Add a public extension method marked with [Decompile]:

[Decompile]
public static IOrderedQueryable<T> OrderBySequence<T, TKey>(
    this IQueryable<T> source, 
    Expression<Func<T, TKey>> keySelector, 
    IEnumerable<TKey> explicitSequence)
    where T : class
    where TKey : IEquatable<TKey>
{
    return (IOrderedQueryable<T>)source.Provider.CreateQuery(
        BuildOrderBySequenceExpression(source.Expression, keySelector, explicitSequence));
}

[Decompile]
// this extension allows to work also on nested navigation properties collections
public static IList<T> OrderBySequence<T, TKey>(this IEnumerable<T> source, IEnumerable<TKey> explicitSequence, Expression<Func<T, TKey>> matchSelector)
    where T : class
    where TKey : IEquatable<TKey>
{
    return (IList<T>)BuildOrderBySequenceExpression(() => source, explicitSequence, matchSelector);
}

You can now use it directly into your queries

var priorityOrder = new[] { 3, 1, 2 };
var results = queryableSource
    .OrderBySequence(o => o.Priority, priorityOrder)
    .ToList();

The expression tree is built at runtime based on the actual sequence values coming either from a local variable or function/contextual parameters. Both produce equivalent expression trees, but the second approach is cleaner and reusable across the codebase.

What Changes ?

  • new [ExpressionFactory] Attribute - Marks methods as expression tree factories
  • new ExpressionFactoryVisitor - Processes factory methods during the decompilation pipeline to revert expressions into the actual arguments expected by the ExpressionFactory (this part is still in progress)
  • new Build() Extension Method - Orchestrates the complete decompilation pipeline
  • DecompiledQueryProvider - Now uses Build() for complete expression processing
  • DecompiledQueryable - Enumeration logic updated to use Build()

Use Cases

This feature would be particularly valuable for:

  • Complex filtering/ordering patterns with variable runtime criteria
  • Domain-specific query operations
  • Reusable query components that adapt to runtime data

There is no breaking changes since this is a purely additive feature. All existing code continues to work without modification.

Do you think this could be added to a future release ? Any insight is welcome.

magicmoux avatar Nov 04 '25 01:11 magicmoux

Sorry, not really understanding what needs to be done. Can you provide more examples and what does what?

hazzik avatar Nov 04 '25 04:11 hazzik

@magicmoux can you elaborate?

hazzik avatar Nov 19 '25 03:11 hazzik

Sorry @hazzik, but not possible at the moment cause I'm stuck in the hospital for a while. Also I didn't take time to push the latest versions and detected what could induce unwanted responsibility on DD's side.

I'll get back to you asap.

Max.

magicmoux avatar Nov 19 '25 08:11 magicmoux

Np. Get well.

hazzik avatar Nov 19 '25 09:11 hazzik

Thx

magicmoux avatar Nov 19 '25 09:11 magicmoux

Hi @hazzik,

Finally feeling better so I killed some time to clean up the FR, bring it up to date with your latest commits and provide the complement of informations you asked for.

You can check the results at https://github.com/magicmoux/DelegateDecompiler/tree/FEAT-ExpressionFactoryExtensions

I provided the explanations into the branch's README.

Please tell me what you think about the concept and whether it could be integrated into DD.

Thanx for your insights, Max.

magicmoux avatar Nov 27 '25 22:11 magicmoux