Feature request - Add an extension point to process expressions built at runtime within the DD process chain
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 usesBuild()for complete expression processingDecompiledQueryable- Enumeration logic updated to useBuild()
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.
Sorry, not really understanding what needs to be done. Can you provide more examples and what does what?
@magicmoux can you elaborate?
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.
Np. Get well.
Thx
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.