From 5c4998c47c2204ba295bb1ed0fe3964fdcbd486c Mon Sep 17 00:00:00 2001 From: Matt Edwards Date: Mon, 21 Oct 2024 17:15:39 -0400 Subject: [PATCH] WIP: just a backup. --- .../Hyperbee.Pipeline.Auth.csproj | 2 +- .../Binders/Abstractions/Binder.cs | 88 +++++++++++-- .../Binders/Abstractions/BlockBinder.cs | 20 ++- .../Abstractions/ConditionalBlockBinder.cs | 48 +++++-- .../Binders/Abstractions/StatementBinder.cs | 121 ++++++++++++++++-- .../Binders/CallBlockBinder.cs | 51 ++++++-- .../Binders/CallIfBlockBinder.cs | 51 ++++++-- .../Binders/CallStatementBinder.cs | 78 ++++++++--- .../Binders/ForEachBlockBinder.cs | 72 ++++++++--- src/Hyperbee.Pipeline/Binders/HookBinder.cs | 57 +++++++-- .../Binders/PipeBlockBinder.cs | 50 ++++++-- .../Binders/PipeIfBlockBinder.cs | 61 +++++++-- .../Binders/PipeStatementBinder.cs | 68 ++++++++-- .../Binders/ReduceBlockBinder.cs | 84 +++++++++--- .../Binders/WaitAllBlockBinder.cs | 104 +++++++-------- src/Hyperbee.Pipeline/Binders/WrapBinder.cs | 82 +++++++++--- .../Builders/CallBlockBuilder.cs | 28 +++- .../Builders/CallIfBlockBuilder.cs | 9 +- .../Builders/CallStatementBuilder.cs | 88 ++++++++----- .../Builders/ForEachBlockBuilder.cs | 3 +- src/Hyperbee.Pipeline/Builders/HookBuilder.cs | 6 +- .../Builders/PipeIfBlockBuilder.cs | 7 +- .../Builders/PipeStatementBuilder.cs | 30 +++-- .../Builders/ReduceBlockBuilder.cs | 7 +- .../Builders/WaitAllBlockBuilder.cs | 9 +- src/Hyperbee.Pipeline/Builders/WrapBuilder.cs | 12 +- .../Hyperbee.Pipeline.csproj | 5 +- src/Hyperbee.Pipeline/IPipelineBuilder.cs | 4 +- src/Hyperbee.Pipeline/IPipelineFunction.cs | 10 +- src/Hyperbee.Pipeline/PipelineBuilder.cs | 41 ++++-- src/Hyperbee.Pipeline/PipelineFactory.cs | 6 +- .../Hyperbee.Pipeline.Caching.csproj | 2 +- .../PipelineDistributedCacheExtensions.cs | 3 +- .../PipelineMemoryCacheExtensions.cs | 6 +- .../Hyperbee.Pipeline.Auth.Tests.csproj | 6 +- .../Hyperbee.Pipeline.Tests.csproj | 6 +- .../Hyperbee.Pipeline.Caching.Tests.csproj | 8 +- 37 files changed, 1016 insertions(+), 317 deletions(-) diff --git a/src/Hyperbee.Pipeline.Auth/Hyperbee.Pipeline.Auth.csproj b/src/Hyperbee.Pipeline.Auth/Hyperbee.Pipeline.Auth.csproj index fb8b206..f69d011 100644 --- a/src/Hyperbee.Pipeline.Auth/Hyperbee.Pipeline.Auth.csproj +++ b/src/Hyperbee.Pipeline.Auth/Hyperbee.Pipeline.Auth.csproj @@ -32,7 +32,7 @@ True \ - + all diff --git a/src/Hyperbee.Pipeline/Binders/Abstractions/Binder.cs b/src/Hyperbee.Pipeline/Binders/Abstractions/Binder.cs index eb97279..916a91d 100644 --- a/src/Hyperbee.Pipeline/Binders/Abstractions/Binder.cs +++ b/src/Hyperbee.Pipeline/Binders/Abstractions/Binder.cs @@ -1,26 +1,94 @@ -using Hyperbee.Pipeline.Context; -using Hyperbee.Pipeline.Extensions.Implementation; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Context; + +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; + namespace Hyperbee.Pipeline.Binders.Abstractions; internal abstract class Binder { - protected FunctionAsync Pipeline { get; } - protected Action Configure { get; } + protected Expression> Pipeline { get; } + protected Expression> Configure { get; } - protected Binder( FunctionAsync function, Action configure ) + protected Binder( Expression> function, Expression> configure ) { Pipeline = function; Configure = configure; } - protected virtual async Task<(TOutput Result, bool Canceled)> ProcessPipelineAsync( IPipelineContext context, TInput argument ) + // protected virtual Task<(TOutput Result, bool Canceled)> ProcessPipelineAsync( IPipelineContext context, TInput argument ) + // { + // var result = await Pipeline( context, argument ).ConfigureAwait( false ); + // + // var contextControl = (IPipelineContextControl) context; + // var canceled = contextControl.HandleCancellationRequested( result ); + // + // return (canceled ? default : result, canceled); + // } + + protected virtual Expression ProcessPipelineAsync( ParameterExpression context, ParameterExpression argument ) { - var result = await Pipeline( context, argument ).ConfigureAwait( false ); + var tupleCtor = typeof(ValueTuple).GetConstructor( [typeof(TOutput), typeof(bool)] )!; + + var resultVariable = Variable( typeof( TOutput ), "result" ); + var canceledVariable = Variable( typeof( bool ), "canceled" ); + + var contextControl = Convert( context , typeof( IPipelineContextControl ) ); - var contextControl = (IPipelineContextControl) context; - var canceled = contextControl.HandleCancellationRequested( result ); + var body = BlockAsync( + [resultVariable, canceledVariable], + Assign( resultVariable, Await( Invoke( Pipeline, context, argument ), configureAwait: false ) ), + Assign( canceledVariable, HandleCancellationRequested( contextControl, resultVariable ) ), - return (canceled ? default : result, canceled); + Condition( + canceledVariable, + New( tupleCtor, Default( typeof( TOutput ) ), canceledVariable ), + New( tupleCtor, resultVariable, canceledVariable ) + ) + ); + + return body; } + + + + /* + public static bool HandleCancellationRequested( this IPipelineContextControl control, TOutput value ) + { + if ( !control.CancellationToken.IsCancellationRequested ) + return false; + + if ( !control.HasCancellationValue ) + control.CancellationValue = value; + + return true; + } + */ + + + private Expression HandleCancellationRequested( Expression contextControl, Expression resultVariable ) + { + var hasCancellationValue = Property( contextControl, "HasCancellationValue" ); + var cancellationTokenProperty = Property( contextControl, "CancellationToken" ); + var cancellationValueProperty = Property( contextControl, "CancellationValue" ); + + var conditionalExpression = Condition( + Not( Property( cancellationTokenProperty, "IsCancellationRequested" ) ), + Constant( false ), + + Block( + IfThen( + Not( hasCancellationValue ), + Assign( cancellationValueProperty, resultVariable ) + ), + // After the assignment, return true + Constant( true ) + ) + ); + + return conditionalExpression; + } + } diff --git a/src/Hyperbee.Pipeline/Binders/Abstractions/BlockBinder.cs b/src/Hyperbee.Pipeline/Binders/Abstractions/BlockBinder.cs index 834d976..81965f6 100644 --- a/src/Hyperbee.Pipeline/Binders/Abstractions/BlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/Abstractions/BlockBinder.cs @@ -1,10 +1,14 @@ -using Hyperbee.Pipeline.Context; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Context; + +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders.Abstractions; internal abstract class BlockBinder : Binder { - protected BlockBinder( FunctionAsync function, Action configure ) + protected BlockBinder( Expression> function, Expression> configure ) : base( function, configure ) { } @@ -13,8 +17,16 @@ protected BlockBinder( FunctionAsync function, Action ProcessBlockAsync( FunctionAsync blockFunction, IPipelineContext context, TArgument nextArgument ) + // protected virtual async Task ProcessBlockAsync( Expression> blockFunction, IPipelineContext context, TArgument nextArgument ) + // { + // return await blockFunction( context, nextArgument ).ConfigureAwait( false ); + // } + protected virtual Expression> ProcessBlockAsync( Expression> blockFunction, ParameterExpression context, Expression nextArgument ) { - return await blockFunction( context, nextArgument ).ConfigureAwait( false ); + var body = BlockAsync( + Await( Invoke( blockFunction, context, nextArgument ), configureAwait: false ) + ); + + return Lambda>( body ); } } diff --git a/src/Hyperbee.Pipeline/Binders/Abstractions/ConditionalBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/Abstractions/ConditionalBlockBinder.cs index 6f23e81..66520ff 100644 --- a/src/Hyperbee.Pipeline/Binders/Abstractions/ConditionalBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/Abstractions/ConditionalBlockBinder.cs @@ -1,31 +1,51 @@ -using System.Runtime.CompilerServices; +using System.Linq.Expressions; using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; namespace Hyperbee.Pipeline.Binders.Abstractions; internal abstract class ConditionalBlockBinder : BlockBinder { - protected Function Condition { get; } + protected Expression> Condition { get; } - protected ConditionalBlockBinder( Function condition, FunctionAsync function, Action configure ) + protected ConditionalBlockBinder( Expression> condition, Expression> function, Expression> configure ) : base( function, configure ) { Condition = condition; } - protected override async Task ProcessBlockAsync( FunctionAsync blockFunction, IPipelineContext context, TArgument nextArgument ) - { - if ( Condition != null && !Condition( context, CastTypeArg( nextArgument ) ) ) - { - return CastTypeArg( nextArgument ); - } + // protected override async Task ProcessBlockAsync( FunctionAsync blockFunction, IPipelineContext context, TArgument nextArgument ) + // { + // if ( Condition != null && !Condition( context, CastTypeArg( nextArgument ) ) ) + // { + // return CastTypeArg( nextArgument ); + // } + // + // return await base.ProcessBlockAsync( blockFunction, context, nextArgument ).ConfigureAwait( false ); + // } - return await base.ProcessBlockAsync( blockFunction, context, nextArgument ).ConfigureAwait( false ); - } + // [MethodImpl( MethodImplOptions.AggressiveInlining )] + // private static TResult CastTypeArg( TType input ) + // { + // return (TResult) (object) input; + // } - [MethodImpl( MethodImplOptions.AggressiveInlining )] - private static TResult CastTypeArg( TType input ) + protected override Expression> ProcessBlockAsync( + Expression> blockFunction, + ParameterExpression context, + Expression nextArgument ) { - return (TResult) (object) input; + if ( Condition == null ) + return base.ProcessBlockAsync( blockFunction, context, nextArgument ); + + var nextArgumentExpression = Constant( nextArgument ); + + return Lambda>( + IfThenElse( + Not( Invoke( Condition, Constant( context ), + Convert( Convert( nextArgumentExpression, typeof(object) ), typeof(TOutput) ) ) ), + Convert( Convert( Constant( nextArgument ), typeof(object) ), typeof(TNext) ), + base.ProcessBlockAsync( blockFunction, context, nextArgument ) + ) ); } } diff --git a/src/Hyperbee.Pipeline/Binders/Abstractions/StatementBinder.cs b/src/Hyperbee.Pipeline/Binders/Abstractions/StatementBinder.cs index b5fb44c..0e3efaa 100644 --- a/src/Hyperbee.Pipeline/Binders/Abstractions/StatementBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/Abstractions/StatementBinder.cs @@ -1,31 +1,124 @@ -using Hyperbee.Pipeline.Context; -using Hyperbee.Pipeline.Extensions.Implementation; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders.Abstractions; internal abstract class StatementBinder : Binder { - protected MiddlewareAsync Middleware { get; } + protected Expression> Middleware { get; } - protected StatementBinder( FunctionAsync function, MiddlewareAsync middleware, Action configure ) + protected StatementBinder( Expression> function, Expression> middleware, Expression> configure ) : base( function, configure ) { Middleware = middleware; } - protected virtual async Task ProcessStatementAsync( FunctionAsync nextFunction, IPipelineContext context, TOutput nextArgument, string frameName ) + // protected MiddlewareAsync Middleware1 { get; } + // protected virtual async Task ProcessStatementAsync( FunctionAsync nextFunction, IPipelineContext context, TOutput nextArgument, string frameName ) + // { + // var contextControl = (IPipelineContextControl) context; + // + // using var _ = contextControl.CreateFrame( context, Configure, frameName ); + // + // if ( Middleware1 == null ) + // return await nextFunction( context, nextArgument ).ConfigureAwait( false ); + // + // return (TNext) await Middleware1( + // context, + // nextArgument, + // async ( context1, argument1 ) => await nextFunction( context1, (TOutput) argument1 ).ConfigureAwait( false ) + // ).ConfigureAwait( false ); + // } + + protected virtual Expression ProcessStatementAsync( Expression> nextFunction, + ParameterExpression context, Expression nextArgument, string frameName ) { - var contextControl = (IPipelineContextControl) context; + // if ( Middleware == null ) + // return await nextFunction( context, nextArgument ).ConfigureAwait( false ); + if ( Middleware == null ) + { + return Invoke( nextFunction, context, nextArgument ); //, configureAwait: false ); - using var _ = contextControl.CreateFrame( context, Configure, frameName ); + //using var _ = contextControl.CreateFrame( context, Configure, frameName ); + // return CreateFrameExpression( + // Convert( context, typeof(IPipelineContextControl) ), + // context, + // Configure, + // Await( Invoke( nextFunction, context, nextArgument ), configureAwait: false ), + // frameName ); + } - if ( Middleware == null ) - return await nextFunction( context, nextArgument ).ConfigureAwait( false ); + // async ( context1, argument1 ) => await nextFunction( context1, (TOutput) argument1 ).ConfigureAwait( false ) + var context1 = Parameter( typeof(IPipelineContext), "context1" ); + var argument1 = Parameter( typeof(object), "argument1" ); + + var middlewareNext = Lambda>( + BlockAsync( + Convert( Await( + Invoke( nextFunction, context1, Convert( argument1, typeof(TOutput) ) ), + configureAwait: false ), + typeof(object) ) + ), + parameters: [context1, argument1] + ); + + // return (TNext) await Middleware( + // context, + // nextArgument, + // middlewareNext + // ).ConfigureAwait( false ); + return + //using var _ = contextControl.CreateFrame( context, Configure, frameName ); + // CreateFrameExpression( + // Convert( Constant( context ), typeof(IPipelineContextControl) ), + // context, + // Configure, + BlockAsync( + Convert( + Await( + Invoke( Middleware, + context, + nextArgument, + middlewareNext + ), + configureAwait: false ), + typeof(TNext) )); //, + // frameName ); //); + } + + public static Expression CreateFrameExpression( + Expression controlParam, + Expression contextParam, + Expression> config, + Expression body, + string defaultName = null + ) + { + var nameVariable = Variable( typeof( string ), "originalName" ); + var idVariable = Variable( typeof( int ), "originalId" ); + + var idProperty = Property( controlParam, "Id" ); + var nameProperty = Property( controlParam, "Name" ); - return (TNext) await Middleware( - context, - nextArgument, - async ( context1, argument1 ) => await nextFunction( context1, (TOutput) argument1 ).ConfigureAwait( false ) - ).ConfigureAwait( false ); + return BlockAsync( + [nameVariable, idVariable], + Assign( idVariable, idProperty ), + Assign( nameVariable, nameProperty ), + TryFinally( + Block( + Assign( idProperty, Call( controlParam, "GetNextId", Type.EmptyTypes ) ), + Assign( nameProperty, Constant( defaultName ) ), + config != null + ? Invoke( config, contextParam ) + : Empty(), + body + ), + Block( + Assign( idProperty, idVariable ), + Assign( nameProperty, nameVariable ) + ) ) + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/CallBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/CallBlockBinder.cs index 75ebd4b..66bcee3 100644 --- a/src/Hyperbee.Pipeline/Binders/CallBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/CallBlockBinder.cs @@ -1,25 +1,54 @@ -using Hyperbee.Pipeline.Binders.Abstractions; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders.Abstractions; +using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class CallBlockBinder : BlockBinder { - public CallBlockBinder( FunctionAsync function ) + public CallBlockBinder( Expression> function ) : base( function, default ) { } - public FunctionAsync Bind( FunctionAsync next ) + // public FunctionAsync Bind( FunctionAsync next ) + // { + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); + // return nextArgument; + // }; + // } + + public Expression> Bind( Expression> next ) { - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + + var awaitedResult = Variable( typeof( (TOutput, bool) ), "awaitedResult" ); + var nextArgumentField = Field( awaitedResult, "Item1" ); + var canceledField = Field( awaitedResult, "Item2" ); - if ( canceled ) - return default; + var returnLabel = Label( "return" ); - await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); - return nextArgument; - }; + return Lambda>( + BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( Invoke( ProcessPipelineAsync( context, argument ) ) ) ), + IfThen( canceledField, + Return( returnLabel, Default( typeof(TOutput) ) ) + ), + Await( Invoke( ProcessBlockAsync( next, context, nextArgumentField ) ), configureAwait: false ), + Label( returnLabel, nextArgumentField ) + ), + parameters: [context, argument] + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/CallIfBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/CallIfBlockBinder.cs index 55494c8..222668e 100644 --- a/src/Hyperbee.Pipeline/Binders/CallIfBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/CallIfBlockBinder.cs @@ -1,25 +1,54 @@ -using Hyperbee.Pipeline.Binders.Abstractions; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders.Abstractions; +using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class CallIfBlockBinder : ConditionalBlockBinder { - public CallIfBlockBinder( Function condition, FunctionAsync function ) + public CallIfBlockBinder( Expression> condition, Expression> function ) : base( condition, function, default ) { } - public FunctionAsync Bind( FunctionAsync next ) + // public FunctionAsync Bind( FunctionAsync next ) + // { + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); + // return nextArgument; + // }; + // } + + public Expression> Bind( Expression> next ) { - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + + var awaitedResult = Variable( typeof( (TOutput, bool) ), "awaitedResult" ); + var nextArgumentField = Field( awaitedResult, "Item1" ); + var canceledField = Field( awaitedResult, "Item2" ); - if ( canceled ) - return default; + var returnLabel = Label( "return" ); - await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); - return nextArgument; - }; + return Lambda>( + BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( Invoke( ProcessPipelineAsync( context, argument ) ) ) ), + IfThen( canceledField, + Return( returnLabel, Default( typeof( TOutput ) ) ) + ), + Await( Invoke( ProcessBlockAsync( next, context, nextArgumentField ) ), configureAwait: false ), + Label( returnLabel, nextArgumentField ) + ), + parameters: [context, argument] + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/CallStatementBinder.cs b/src/Hyperbee.Pipeline/Binders/CallStatementBinder.cs index ab4f296..bf937f9 100644 --- a/src/Hyperbee.Pipeline/Binders/CallStatementBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/CallStatementBinder.cs @@ -1,34 +1,74 @@ -using System.Reflection; +using System.Linq.Expressions; +using System.Reflection; using Hyperbee.Pipeline.Binders.Abstractions; using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class CallStatementBinder : StatementBinder { - public CallStatementBinder( FunctionAsync function, MiddlewareAsync middleware, Action configure ) + public CallStatementBinder( Expression> function, Expression> middleware, Expression> configure ) : base( function, middleware, configure ) { } - public FunctionAsync Bind( ProcedureAsync next, MethodInfo method = null ) + // public FunctionAsync Bind( ProcedureAsync next, MethodInfo method = null ) + // { + // var defaultName = (method ?? next.Method).Name; + // + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // return await ProcessStatementAsync( + // async ( ctx, arg ) => + // { + // await next( ctx, arg ).ConfigureAwait( false ); + // return arg; + // }, context, nextArgument, defaultName ).ConfigureAwait( false ); + // }; + // } + + public Expression> Bind( Expression> next, MethodInfo method = null ) { - var defaultName = (method ?? next.Method).Name; - - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); - - if ( canceled ) - return default; - - return await ProcessStatementAsync( - async ( ctx, arg ) => - { - await next( ctx, arg ).ConfigureAwait( false ); - return arg; - }, context, nextArgument, defaultName ).ConfigureAwait( false ); - }; + var defaultName = method?.Name ?? "defaultName"; + + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + + var awaitedResult = Variable( typeof( (TOutput, bool) ), "awaitedResult" ); + var nextArgument = Field( awaitedResult, "Item1" ); + var canceled = Field( awaitedResult, "Item2" ); + + var returnLabel = Label( "return" ); + + // inner function + var ctx = Parameter( typeof( IPipelineContext ), "ctx" ); + var arg = Parameter( typeof( TInput ), "arg" ); + var nextExpression = Lambda> ( + BlockAsync( + Await( Invoke( next, ctx, arg ), configureAwait: false ), + argument + ), + parameters: [ctx, arg] + ); + + return Lambda>( + BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( Invoke( ProcessPipelineAsync( context, argument ) ) ) ), + IfThen( canceled, + Return( returnLabel, Default( typeof( TOutput ) ) ) + ), + Label( returnLabel, Await( Invoke( ProcessStatementAsync( nextExpression, context, nextArgument, defaultName ) ), configureAwait: false ) ) + ), + parameters: [context, argument] + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/ForEachBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/ForEachBlockBinder.cs index 7c2b00a..3697798 100644 --- a/src/Hyperbee.Pipeline/Binders/ForEachBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/ForEachBlockBinder.cs @@ -1,33 +1,75 @@ -using Hyperbee.Pipeline.Binders.Abstractions; +using System.Collections; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders.Abstractions; +using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class ForEachBlockBinder : BlockBinder { - public ForEachBlockBinder( FunctionAsync function ) + public ForEachBlockBinder( Expression> function ) : base( function, default ) { } - public FunctionAsync Bind( FunctionAsync next ) + // public FunctionAsync Bind( FunctionAsync next ) + // { + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // var nextArguments = (IEnumerable) nextArgument; + // + // foreach ( var elementArgument in nextArguments ) + // { + // await ProcessBlockAsync( next, context, elementArgument ).ConfigureAwait( false ); + // } + // + // return nextArgument; + // }; + // } + public Expression> Bind( Expression> next ) { - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); - if ( canceled ) - return default; + var awaitedResult = Variable( typeof( (TOutput, bool) ), "awaitedResult" ); + var nextArgument = Field( awaitedResult, "Item1" ); + var canceled = Field( awaitedResult, "Item2" ); - var nextArguments = (IEnumerable) nextArgument; + var nextArguments = Variable( typeof( IEnumerable ), "nextArguments" ); + var moveNextCall = Call( nextArguments, typeof(IEnumerator).GetMethod( "MoveNext" )! ); - foreach ( var elementArgument in nextArguments ) - { - await ProcessBlockAsync( next, context, elementArgument ).ConfigureAwait( false ); - } + var breakLabel = Label( "breakLoop" ); + var returnLabel = Label( "return" ); - return nextArgument; - }; + return Lambda>( + BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( Invoke( ProcessPipelineAsync( context, argument ) ) ) ), + IfThen( canceled, + Return( returnLabel, Default( typeof( TOutput ) ) ) + ), + Assign( nextArguments, Convert( nextArgument, typeof( IEnumerable ) ) ), + + Loop( + IfThenElse( IsTrue( moveNextCall ), + Await( Invoke( ProcessBlockAsync( next, context, nextArgument ) ), configureAwait: false ), + Label( breakLabel ) + ), + breakLabel + ), + + Label( returnLabel, nextArgument ) + ), + parameters: [context, argument] + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/HookBinder.cs b/src/Hyperbee.Pipeline/Binders/HookBinder.cs index 5ece4da..a755d00 100644 --- a/src/Hyperbee.Pipeline/Binders/HookBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/HookBinder.cs @@ -1,21 +1,56 @@ -namespace Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Context; + +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; + +namespace Hyperbee.Pipeline.Binders; internal class HookBinder // explicit Type Args due to usage { - private MiddlewareAsync Middleware { get; } + private Expression> Middleware { get; } - public HookBinder( MiddlewareAsync middleware ) + public HookBinder( Expression> middleware ) { - Middleware = middleware ?? (async ( context, argument, next ) => await next( context, argument ).ConfigureAwait( false )); + Middleware = middleware; // Note: no need to create empty middleware just don't execute it. } - public MiddlewareAsync Bind( MiddlewareAsync middleware ) + // public MiddlewareAsync Bind( MiddlewareAsync middleware ) + // { + // return async ( context, argument, function ) => + // await middleware( + // context, + // argument, + // async ( context1, argument1 ) => await Middleware( context1, argument1, function ).ConfigureAwait( false ) + // ).ConfigureAwait( false ); + // } + + public Expression> Bind( Expression> middleware ) { - return async ( context, argument, function ) => - await middleware( - context, - argument, - async ( context1, argument1 ) => await Middleware( context1, argument1, function ).ConfigureAwait( false ) - ).ConfigureAwait( false ); + if( Middleware == null ) + return middleware; + + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + var function = Parameter( typeof( FunctionAsync ), "function" ); + + // inner function + var ctx = Parameter( typeof( IPipelineContext ), "ctx" ); + var arg = Parameter( typeof( TInput ), "arg" ); + var nextExpression = Lambda>( + BlockAsync( + Await( Invoke( Middleware, ctx, arg, function ), configureAwait: false ), + argument + ), + parameters: [ctx, arg] + ); + + return Lambda>( + BlockAsync( + [context, argument], + Await( Invoke( middleware, context, argument, nextExpression ), configureAwait: false ) + ), + parameters: [context, argument, function] ); } + } diff --git a/src/Hyperbee.Pipeline/Binders/PipeBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/PipeBlockBinder.cs index 7b081a7..22d367c 100644 --- a/src/Hyperbee.Pipeline/Binders/PipeBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/PipeBlockBinder.cs @@ -1,24 +1,54 @@ -using Hyperbee.Pipeline.Binders.Abstractions; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders.Abstractions; +using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class PipeBlockBinder : BlockBinder { - public PipeBlockBinder( FunctionAsync function ) + public PipeBlockBinder( Expression> function ) : base( function, default ) { } - public FunctionAsync Bind( FunctionAsync next ) + // public Expression> Bind( Expression> next ) + // { + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // return await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); + // }; + // } + + public Expression> Bind( Expression> next ) { - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TNext ), "argument" ); + + var awaitedResult = Variable( typeof( (TNext, bool) ), "awaitedResult" ); + var nextArgumentField = Field( awaitedResult, "Item1" ); + var canceledField = Field( awaitedResult, "Item2" ); - if ( canceled ) - return default; + var returnLabel = Label( "return" ); - return await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); - }; + return Lambda>( + BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( Invoke( ProcessPipelineAsync( context, argument ) ) ) ), + IfThen( canceledField, + Return( returnLabel, Default( typeof(TNext) ) ) + ), + Label( returnLabel, + Await( Invoke( ProcessBlockAsync( next, context, nextArgumentField ) ), configureAwait: false ) + ) + ), + parameters: [context, argument] + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/PipeIfBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/PipeIfBlockBinder.cs index 16219d1..758142f 100644 --- a/src/Hyperbee.Pipeline/Binders/PipeIfBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/PipeIfBlockBinder.cs @@ -1,24 +1,65 @@ -using Hyperbee.Pipeline.Binders.Abstractions; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders.Abstractions; +using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class PipeIfBlockBinder : ConditionalBlockBinder { - public PipeIfBlockBinder( Function condition, FunctionAsync function ) + public PipeIfBlockBinder( Expression> condition, Expression> function ) : base( condition, function, default ) { } - public FunctionAsync Bind( FunctionAsync next ) + // public FunctionAsync Bind( FunctionAsync next ) + // { + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // return await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); + // }; + // } + + public Expression> Bind( Expression> next ) { - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + + var awaitedResult = Variable( typeof( (TOutput, bool) ), "awaitedResult" ); + var nextArgument = Field( awaitedResult, "Item1" ); + var canceled = Field( awaitedResult, "Item2" ); + + var returnLabel = Label( "return" ); - if ( canceled ) - return default; + // inner function + var ctx = Parameter( typeof( IPipelineContext ), "ctx" ); + var arg = Parameter( typeof( TInput ), "arg" ); + var nextExpression = Lambda>( + BlockAsync( + Await( Invoke( next, ctx, arg ), configureAwait: false ), + argument + ), + parameters: [ctx, arg] + ); - return await ProcessBlockAsync( next, context, nextArgument ).ConfigureAwait( false ); - }; + return Lambda>( + BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( Invoke( ProcessPipelineAsync( context, argument ) ) ) ), + IfThen( canceled, + Return( returnLabel, Default( typeof(TNext) ) ) + ), + Label( returnLabel, + Await( Invoke( ProcessBlockAsync( nextExpression, context, nextArgument ) ), configureAwait: false ) + ) + ), + parameters: [context, argument] + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/PipeStatementBinder.cs b/src/Hyperbee.Pipeline/Binders/PipeStatementBinder.cs index cfdb841..41b4b45 100644 --- a/src/Hyperbee.Pipeline/Binders/PipeStatementBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/PipeStatementBinder.cs @@ -1,28 +1,74 @@ -using System.Reflection; +using System.Linq.Expressions; +using System.Reflection; using Hyperbee.Pipeline.Binders.Abstractions; using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class PipeStatementBinder : StatementBinder { - public PipeStatementBinder( FunctionAsync function, MiddlewareAsync middleware, Action configure ) + public PipeStatementBinder( Expression> function, Expression> middleware, Expression> configure ) : base( function, middleware, configure ) { } - public FunctionAsync Bind( FunctionAsync next, MethodInfo method = null ) + // public Expression> Bind( Expression> next, MethodInfo method = null ) + // { + // var defaultName = method?.Name ?? "name"; + // + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // return await ProcessStatementAsync( next, context, nextArgument, defaultName ).ConfigureAwait( false ); + // }; + // } + + + public Expression> Bind( Expression> next, MethodInfo method = null ) { - var defaultName = (method ?? next.Method).Name; + var defaultName = method?.Name ?? "defaultName"; + + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + + var awaitedResult = Variable( typeof( (TOutput, bool) ), "awaitedResult" ); + var nextArgument = Field( awaitedResult, "Item1" ); + var canceled = Field( awaitedResult, "Item2" ); - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + var body = BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( ProcessPipelineAsync( context, argument ) ) ), + Condition( canceled, + Default( typeof(TNext) ), + Await( ProcessStatementAsync( next, context, nextArgument, defaultName ), configureAwait: false ) + ) + ); - if ( canceled ) - return default; + return Lambda>( + body, + parameters: [context, argument] + ); - return await ProcessStatementAsync( next, context, nextArgument, defaultName ).ConfigureAwait( false ); - }; + // + // var body = BlockAsync( + // [awaitedResult], + // Assign( awaitedResult, Await( ProcessPipelineAsync( context, argument ) ) ), + // IfThen( canceled, + // Return( returnLabel, Default( typeof(TNext) ) ) + // ), + // Label( returnLabel, + // Await( ProcessStatementAsync( next, context, nextArgument, defaultName ), configureAwait: false ) ) + // ); + // + // return Lambda>( + // body, + // parameters: [context, argument] + // ); } } diff --git a/src/Hyperbee.Pipeline/Binders/ReduceBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/ReduceBlockBinder.cs index a184fb0..0104292 100644 --- a/src/Hyperbee.Pipeline/Binders/ReduceBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/ReduceBlockBinder.cs @@ -1,38 +1,84 @@ -using Hyperbee.Pipeline.Binders.Abstractions; +using System.Collections; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders.Abstractions; +using Hyperbee.Pipeline.Context; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class ReduceBlockBinder : BlockBinder { - private Func Reducer { get; } + private Expression> Reducer { get; } - public ReduceBlockBinder( Func reducer, FunctionAsync function ) + public ReduceBlockBinder( Expression> reducer, Expression> function ) : base( function, default ) { Reducer = reducer; } - public FunctionAsync Bind( FunctionAsync next ) + // public FunctionAsync Bind( FunctionAsync next ) + // { + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // var nextArguments = (IEnumerable) nextArgument; + // var accumulator = default( TNext ); + // + // // Process each element and apply the reducer + // foreach ( var elementArgument in nextArguments ) + // { + // var result = await ProcessBlockAsync( next, context, elementArgument ).ConfigureAwait( false ); + // accumulator = Reducer( accumulator, result ); + // } + // + // return accumulator; + // }; + // } + + public Expression> Bind( Expression> next ) { - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + + var awaitedResult = Variable( typeof( (TNext, bool) ), "awaitedResult" ); + var blockResult = Variable( typeof( (TNext, bool) ), "blockResult" ); + var nextArgument = Field( awaitedResult, "Item1" ); + var canceled = Field( awaitedResult, "Item2" ); + + var nextArguments = Variable( typeof( IEnumerable ), "nextArguments" ); + var moveNextCall = Call( nextArguments, typeof( IEnumerator ).GetMethod( "MoveNext" )! ); + + var breakLabel = Label( "breakLoop" ); + var returnLabel = Label( "return" ); - if ( canceled ) - return default; + // TODO: get next result and call accumulator/reducer - var nextArguments = (IEnumerable) nextArgument; - var accumulator = default( TNext ); + return Lambda>( + BlockAsync( + [awaitedResult], + Assign( awaitedResult, Await( Invoke( ProcessPipelineAsync( context, argument ) ) ) ), + IfThen( canceled, + Return( returnLabel, Default( typeof( TNext ) ) ) + ), + Assign( nextArguments, Convert( nextArgument, typeof( IEnumerable ) ) ), - // Process each element and apply the reducer - foreach ( var elementArgument in nextArguments ) - { - var result = await ProcessBlockAsync( next, context, elementArgument ).ConfigureAwait( false ); - accumulator = Reducer( accumulator, result ); - } + Loop( + IfThenElse( IsTrue( moveNextCall ), + Await( Invoke( ProcessBlockAsync( next, context, nextArgument ) ), configureAwait: false ), + Label( breakLabel ) + ), + breakLabel + ), - return accumulator; - }; + Label( returnLabel, nextArgument ) + ), + parameters: [context, argument] + ); } } diff --git a/src/Hyperbee.Pipeline/Binders/WaitAllBlockBinder.cs b/src/Hyperbee.Pipeline/Binders/WaitAllBlockBinder.cs index e93eea9..6770d3f 100644 --- a/src/Hyperbee.Pipeline/Binders/WaitAllBlockBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/WaitAllBlockBinder.cs @@ -1,21 +1,24 @@ -using Hyperbee.Pipeline.Binders.Abstractions; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders.Abstractions; using Hyperbee.Pipeline.Context; using Hyperbee.Pipeline.Extensions; using Hyperbee.Pipeline.Extensions.Implementation; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline.Binders; internal class WaitAllBlockBinder : ConditionalBlockBinder { - private MiddlewareAsync Middleware { get; } + private Expression> Middleware { get; } - public WaitAllBlockBinder( FunctionAsync function, MiddlewareAsync middleware, Action configure ) + public WaitAllBlockBinder( Expression> function, Expression> middleware, Expression> configure ) : this( null, function, middleware, configure ) { } - public WaitAllBlockBinder( Function condition, FunctionAsync function, MiddlewareAsync middleware, Action configure ) + public WaitAllBlockBinder( Expression> condition, Expression> function, Expression> middleware, Expression> configure ) : base( condition, function, configure ) { Middleware = middleware; @@ -25,51 +28,52 @@ public FunctionAsync Bind( FunctionAsync[ { ArgumentNullException.ThrowIfNull( reducer ); - return async ( context, argument ) => - { - var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); - - if ( canceled ) - return default; - - // WaitAllBlockBinder is unique in that it is both a block configure and a step. - // The reducer is the step action, and because it is a step, we need to ensure - // that middleware is called. Middleware requires us to pass in the execution - // function that it wraps. This requires an additional level of wrapping. - - return await WaitAllAsync( context, nextArgument, nexts, reducer ).ConfigureAwait( false ); - }; - } - - private async Task WaitAllAsync( IPipelineContext context, TOutput nextArgument, FunctionAsync[] nexts, WaitAllReducer reducer ) - { - var contextControl = (IPipelineContextControl) context; - using var _ = contextControl.CreateFrame( context, Configure, nameof( WaitAllAsync ) ); - - var results = new WaitAllResult[nexts.Length]; - var items = nexts.Select( ( x, i ) => new { next = x, index = i } ); - - await items.ForEachAsync( async item => - { - var innerContext = context.Clone( false ); // context fork - - var result = await ProcessStatementAsync( item.next, innerContext, nextArgument ).ConfigureAwait( false ); - - results[item.index] = new WaitAllResult { Context = innerContext, Result = result }; - } ).ConfigureAwait( false ); - - return reducer( context, nextArgument, results ); - } - - private async Task ProcessStatementAsync( FunctionAsync next, IPipelineContext context, TOutput nextArgument ) - { - if ( Middleware == null ) - return await next( context, nextArgument ).ConfigureAwait( false ); - - return await Middleware( - context, - nextArgument, - async ( context1, argument1 ) => await next( context1, (TOutput) argument1 ).ConfigureAwait( false ) - ).ConfigureAwait( false ); + return null; + // return async ( context, argument ) => + // { + // var (nextArgument, canceled) = await ProcessPipelineAsync( context, argument ).ConfigureAwait( false ); + // + // if ( canceled ) + // return default; + // + // // WaitAllBlockBinder is unique in that it is both a block configure and a step. + // // The reducer is the step action, and because it is a step, we need to ensure + // // that middleware is called. Middleware requires us to pass in the execution + // // function that it wraps. This requires an additional level of wrapping. + // + // return await WaitAllAsync( context, nextArgument, nexts, reducer ).ConfigureAwait( false ); + // }; } + // + // private async Task WaitAllAsync( IPipelineContext context, TOutput nextArgument, FunctionAsync[] nexts, WaitAllReducer reducer ) + // { + // var contextControl = (IPipelineContextControl) context; + // using var _ = contextControl.CreateFrame( context, Configure, nameof( WaitAllAsync ) ); + // + // var results = new WaitAllResult[nexts.Length]; + // var items = nexts.Select( ( x, i ) => new { next = x, index = i } ); + // + // await items.ForEachAsync( async item => + // { + // var innerContext = context.Clone( false ); // context fork + // + // var result = await ProcessStatementAsync( item.next, innerContext, nextArgument ).ConfigureAwait( false ); + // + // results[item.index] = new WaitAllResult { Context = innerContext, Result = result }; + // } ).ConfigureAwait( false ); + // + // return reducer( context, nextArgument, results ); + // } + // + // private async Task ProcessStatementAsync( FunctionAsync next, IPipelineContext context, TOutput nextArgument ) + // { + // if ( Middleware == null ) + // return await next( context, nextArgument ).ConfigureAwait( false ); + // + // return await Middleware( + // context, + // nextArgument, + // async ( context1, argument1 ) => await next( context1, (TOutput) argument1 ).ConfigureAwait( false ) + // ).ConfigureAwait( false ); + // } } diff --git a/src/Hyperbee.Pipeline/Binders/WrapBinder.cs b/src/Hyperbee.Pipeline/Binders/WrapBinder.cs index 471738f..ceb198d 100644 --- a/src/Hyperbee.Pipeline/Binders/WrapBinder.cs +++ b/src/Hyperbee.Pipeline/Binders/WrapBinder.cs @@ -1,34 +1,86 @@ -using Hyperbee.Pipeline.Context; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Context; using Hyperbee.Pipeline.Extensions.Implementation; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; + namespace Hyperbee.Pipeline.Binders; internal class WrapBinder { - private MiddlewareAsync Middleware { get; } - private Action Configure { get; } + private Expression> Middleware { get; } + private Expression> Configure { get; } - public WrapBinder( MiddlewareAsync middleware, Action configure ) + public WrapBinder( Expression> middleware, Expression> configure ) { Middleware = middleware; Configure = configure; } - public FunctionAsync Bind( FunctionAsync next ) + // public FunctionAsync Bind( FunctionAsync next ) + // { + // var defaultName = next.Method.Name; + // + // return async ( context, argument ) => + // { + // var contextControl = (IPipelineContextControl) context; + // + // using var _ = contextControl.CreateFrame( context, Configure, defaultName ); + // + // return await Middleware( + // context, + // argument, + // async ( context1, argument1 ) => await next( context1, argument1 ).ConfigureAwait( false ) + // ).ConfigureAwait( false ); + // }; + // } + + public Expression> Bind( Expression> next ) { - var defaultName = next.Method.Name; + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); - return async ( context, argument ) => + // if ( Middleware == null ) + // return await nextFunction( context, nextArgument ).ConfigureAwait( false ); + if ( Middleware == null ) { - var contextControl = (IPipelineContextControl) context; + return Lambda>( + Invoke( next, context, argument ), + parameters: [context, argument] ); + } + + // async ( context1, argument1 ) => await nextFunction( context1, (TOutput) argument1 ).ConfigureAwait( false ) + var context1 = Parameter( typeof( IPipelineContext ), "context1" ); + var argument1 = Parameter( typeof( TOutput ), "argument1" ); + + var middlewareNext = Lambda>( + BlockAsync( + Convert( Await( + Invoke( next, context1, argument1 ), + configureAwait: false ), + typeof( TOutput ) ) + ), + parameters: [context1, argument1] + ); - using var _ = contextControl.CreateFrame( context, Configure, defaultName ); + // return (TNext) await Middleware( + // context, + // nextArgument, + // middlewareNext + // ).ConfigureAwait( false ); + return Lambda>( + BlockAsync( + Convert( + Await( + Invoke( Middleware, + context, + argument, + middlewareNext + ), + configureAwait: false ), + typeof( TOutput ) ) ), + parameters: [context, argument] ); - return await Middleware( - context, - argument, - async ( context1, argument1 ) => await next( context1, argument1 ).ConfigureAwait( false ) - ).ConfigureAwait( false ); - }; } } diff --git a/src/Hyperbee.Pipeline/Builders/CallBlockBuilder.cs b/src/Hyperbee.Pipeline/Builders/CallBlockBuilder.cs index 3d57e25..96f2388 100644 --- a/src/Hyperbee.Pipeline/Builders/CallBlockBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/CallBlockBuilder.cs @@ -10,7 +10,7 @@ public static IPipelineBuilder Call( Func, IPipelineBuilder> builder ) { - return CallBlockBuilder.Call( parent, true, builder ); + return CallBlockBuilder.Call( parent, true, b => builder( b ) ); } public static IPipelineBuilder Call( @@ -19,12 +19,33 @@ public static IPipelineBuilder Call( Func, IPipelineBuilder> builder ) { - return CallBlockBuilder.Call( parent, inheritMiddleware, builder ); + return CallBlockBuilder.Call( parent, inheritMiddleware, b => builder( b ) ); } } internal static class CallBlockBuilder { + // public static IPipelineBuilder Call( + // IPipelineBuilder parent, + // bool inheritMiddleware, + // Expression, IPipelineBuilder>> builder + // ) + // { + // ArgumentNullException.ThrowIfNull( builder ); + // + // var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); + // + // var block = PipelineFactory.Start( inheritMiddleware ? parentMiddleware : null ); + // var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); + // var function = CastExpression( parent.CastExpression( builder ); // cast because we don't know the final Pipe output value + // builder( block ).CastFunction(); // cast because we don't know the final Pipe output value + // + // return new PipelineBuilder + // { + // Function = new CallBlockBinder( parentFunction ).Bind( block ), + // Middleware = parentMiddleware + // }; + // } public static IPipelineBuilder Call( IPipelineBuilder parent, bool inheritMiddleware, @@ -36,7 +57,7 @@ Func, IPipelineBuilder> builder var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); var block = PipelineFactory.Start( inheritMiddleware ? parentMiddleware : null ); - var function = builder( block ).CastFunction(); // cast because we don't know the final Pipe output value + var function = builder( block ).CastExpression(); return new PipelineBuilder { @@ -44,4 +65,5 @@ Func, IPipelineBuilder> builder Middleware = parentMiddleware }; } + } diff --git a/src/Hyperbee.Pipeline/Builders/CallIfBlockBuilder.cs b/src/Hyperbee.Pipeline/Builders/CallIfBlockBuilder.cs index 90b7993..3e17598 100644 --- a/src/Hyperbee.Pipeline/Builders/CallIfBlockBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/CallIfBlockBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Extensions.Implementation; namespace Hyperbee.Pipeline; @@ -39,11 +40,13 @@ Func, IPipelineBuilder> builder var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); var block = PipelineFactory.Start( inheritMiddleware ? parentMiddleware : null ); - var function = builder( block ).CastFunction(); // cast because we don't know the final Pipe output value + var function = builder( block ).CastExpression(); // cast because we don't know the final Pipe output value + + Expression> conditionExpression = ( ctx, arg ) => condition( ctx, arg ); return new PipelineBuilder { - Function = new CallIfBlockBinder( condition, parentFunction ).Bind( function ), + Function = new CallIfBlockBinder( conditionExpression, parentFunction ).Bind( function ), Middleware = parentMiddleware }; } diff --git a/src/Hyperbee.Pipeline/Builders/CallStatementBuilder.cs b/src/Hyperbee.Pipeline/Builders/CallStatementBuilder.cs index e061065..90e1b31 100644 --- a/src/Hyperbee.Pipeline/Builders/CallStatementBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/CallStatementBuilder.cs @@ -1,7 +1,9 @@ -using System.Xml.Linq; +using System.Linq.Expressions; +using System.Xml.Linq; using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Context; using Hyperbee.Pipeline.Extensions.Implementation; +using static System.Net.Mime.MediaTypeNames; namespace Hyperbee.Pipeline; @@ -12,7 +14,12 @@ public static IPipelineBuilder Call( Procedure next, string name ) { - return CallStatementBuilder.Call( parent, next, config => config.Name = name ); + Expression> nextExpression = ( ctx, arg ) => Task.Run( () => next( ctx, arg ) ); + Expression> configExpression = name == null + ? null + : ctx => SetName( ctx, name ); + + return CallStatementBuilder.CallAsync( parent, nextExpression, configExpression ); } public static IPipelineBuilder Call( @@ -21,7 +28,12 @@ public static IPipelineBuilder Call( Action config = null ) { - return CallStatementBuilder.Call( parent, next, config ); + Expression> nextExpression = ( ctx, arg ) => Task.Run( () => next( ctx, arg ) ); + Expression> configExpression = config == null + ? null + : ctx => config( ctx ); + + return CallStatementBuilder.CallAsync( parent, nextExpression, configExpression ); } public static IPipelineBuilder CallAsync( @@ -30,7 +42,12 @@ public static IPipelineBuilder CallAsync( string name ) { - return CallStatementBuilder.CallAsync( parent, next, config => config.Name = name ); + Expression> nextExpression = ( ctx, arg ) => next( ctx, arg ); + Expression> configExpression = name == null + ? null + : ctx => SetName( ctx, name ); + + return CallStatementBuilder.CallAsync( parent, nextExpression, configExpression ); } public static IPipelineBuilder CallAsync( @@ -39,41 +56,50 @@ public static IPipelineBuilder CallAsync( Action config = null ) { - return CallStatementBuilder.CallAsync( parent, next, config ); + Expression> nextExpression = ( ctx, arg ) => next( ctx, arg ); + Expression> configExpression = config == null + ? null + : ctx => config( ctx ); + + return CallStatementBuilder.CallAsync( parent, nextExpression, configExpression ); + } + public static void SetName( IPipelineContext ctx, string name ) + { + ctx.Name = name; } } internal static class CallStatementBuilder { - public static IPipelineBuilder Call( - IPipelineBuilder parent, - Procedure next, - Action config = null - ) - { - ArgumentNullException.ThrowIfNull( next ); - - var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); - - return new PipelineBuilder - { - Function = new CallStatementBinder( parentFunction, parentMiddleware, config ).Bind( AsyncNext, next.Method ), - Middleware = parentMiddleware - }; - - // task wrapper - - Task AsyncNext( IPipelineContext context, TOutput argument ) - { - next( context, argument ); - return Task.CompletedTask; - } - } + // public static IPipelineBuilder Call( + // IPipelineBuilder parent, + // Procedure next, + // Action config = null + // ) + // { + // ArgumentNullException.ThrowIfNull( next ); + // + // var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); + // + // return new PipelineBuilder + // { + // Function = new CallStatementBinder( parentFunction, parentMiddleware, config ).Bind( AsyncNext, next.Method ), + // Middleware = parentMiddleware + // }; + // + // // task wrapper + // + // Task AsyncNext( IPipelineContext context, TOutput argument ) + // { + // next( context, argument ); + // return Task.CompletedTask; + // } + // } public static IPipelineBuilder CallAsync( IPipelineBuilder parent, - ProcedureAsync next, - Action config = null + Expression> next, + Expression> config = null ) { ArgumentNullException.ThrowIfNull( next ); diff --git a/src/Hyperbee.Pipeline/Builders/ForEachBlockBuilder.cs b/src/Hyperbee.Pipeline/Builders/ForEachBlockBuilder.cs index 2456159..83e604b 100644 --- a/src/Hyperbee.Pipeline/Builders/ForEachBlockBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/ForEachBlockBuilder.cs @@ -37,7 +37,8 @@ Func, IPipelineBuilder> builder var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); var block = PipelineFactory.Start( inheritMiddleware ? parentMiddleware : null ); - var function = builder( block ).CastFunction(); // cast because we don't know the final Pipe output value + //var function = builder( block ).CastFunction(); // cast because we don't know the final Pipe output value + var function = builder( block ).CastExpression(); // cast because we don't know the final Pipe output value return new PipelineBuilder { diff --git a/src/Hyperbee.Pipeline/Builders/HookBuilder.cs b/src/Hyperbee.Pipeline/Builders/HookBuilder.cs index 41ae3ee..4d92a46 100644 --- a/src/Hyperbee.Pipeline/Builders/HookBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/HookBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Extensions.Implementation; namespace Hyperbee.Pipeline; @@ -34,10 +35,11 @@ MiddlewareAsync functionMiddleware var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); + Expression> middlewareExpression = ( ctx, arg, function ) => functionMiddleware( ctx, arg, function ); return new PipelineBuilder { Function = parentFunction, - Middleware = new HookBinder( parentMiddleware ).Bind( functionMiddleware ) + Middleware = new HookBinder( parentMiddleware ).Bind( middlewareExpression ) }; } diff --git a/src/Hyperbee.Pipeline/Builders/PipeIfBlockBuilder.cs b/src/Hyperbee.Pipeline/Builders/PipeIfBlockBuilder.cs index 596744e..06f974e 100644 --- a/src/Hyperbee.Pipeline/Builders/PipeIfBlockBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/PipeIfBlockBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Extensions.Implementation; namespace Hyperbee.Pipeline; @@ -42,9 +43,11 @@ Func, IPipelineBuilder> var block = PipelineFactory.Start( inheritMiddleware ? parentMiddleware : null ); var function = ((PipelineBuilder) builder( block )).Function; + Expression> conditionExpression = ( ctx, arg ) => condition( ctx, arg ); + return new PipelineBuilder { - Function = new PipeIfBlockBinder( condition, parentFunction ).Bind( function ), + Function = new PipeIfBlockBinder( conditionExpression, parentFunction ).Bind( function ), Middleware = parentMiddleware }; } diff --git a/src/Hyperbee.Pipeline/Builders/PipeStatementBuilder.cs b/src/Hyperbee.Pipeline/Builders/PipeStatementBuilder.cs index 28f4846..e7ec9ce 100644 --- a/src/Hyperbee.Pipeline/Builders/PipeStatementBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/PipeStatementBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Context; using Hyperbee.Pipeline.Extensions.Implementation; @@ -12,7 +13,7 @@ public static IPipelineBuilder Pipe( string name ) { - return PipeStatementBuilder.Pipe( parent, next, config => config.Name = name ); + return PipeStatementBuilder.Pipe( parent, next, ctx => ctx.Name = name ); } public static IPipelineBuilder Pipe( @@ -30,7 +31,7 @@ public static IPipelineBuilder PipeAsync( string name ) { - return PipeStatementBuilder.PipeAsync( parent, next, config => config.Name = name ); + return PipeStatementBuilder.PipeAsync( parent, next, ctx => ctx.Name = name ); } public static IPipelineBuilder PipeAsync( @@ -52,21 +53,19 @@ public static IPipelineBuilder Pipe( ) { ArgumentNullException.ThrowIfNull( next ); - + var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); + Expression> nextExpression = ( ctx, arg ) => Task.FromResult( next( ctx, arg ) ); + Expression> configExpression = config == null + ? null + : ctx => config( ctx ); + return new PipelineBuilder { - Function = new PipeStatementBinder( parentFunction, parentMiddleware, config ).Bind( AsyncNext, next.Method ), + Function = new PipeStatementBinder( parentFunction, parentMiddleware, configExpression ).Bind( nextExpression ), Middleware = parentMiddleware }; - - // task wrapper - - Task AsyncNext( IPipelineContext context, TOutput argument ) - { - return Task.FromResult( next( context, argument ) ); - } } public static IPipelineBuilder PipeAsync( @@ -79,9 +78,14 @@ public static IPipelineBuilder PipeAsync( var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); + Expression> nextExpression = ( ctx, arg ) => next( ctx, arg ); + Expression> configExpression = config == null + ? null + : ctx => config( ctx ); + return new PipelineBuilder { - Function = new PipeStatementBinder( parentFunction, parentMiddleware, config ).Bind( next ), + Function = new PipeStatementBinder( parentFunction, parentMiddleware, configExpression ).Bind( nextExpression ), Middleware = parentMiddleware }; } diff --git a/src/Hyperbee.Pipeline/Builders/ReduceBlockBuilder.cs b/src/Hyperbee.Pipeline/Builders/ReduceBlockBuilder.cs index da7dc2c..8cf02c5 100644 --- a/src/Hyperbee.Pipeline/Builders/ReduceBlockBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/ReduceBlockBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Extensions.Implementation; namespace Hyperbee.Pipeline; @@ -46,9 +47,11 @@ public static IPipelineBuilder ReduceAsync( var block = PipelineFactory.Start( inheritMiddleware ? parentMiddleware : null ); var function = ((PipelineBuilder) builder( block )).Function; + Expression> reducerExpression = ( n1, n2 ) => reducer( n1, n2 ); + return new PipelineBuilder { - Function = new ReduceBlockBinder( reducer, parentFunction ).Bind( function ), + Function = new ReduceBlockBinder( reducerExpression, parentFunction ).Bind( function ), Middleware = parentMiddleware }; } diff --git a/src/Hyperbee.Pipeline/Builders/WaitAllBlockBuilder.cs b/src/Hyperbee.Pipeline/Builders/WaitAllBlockBuilder.cs index 3e1327a..2e8ce3b 100644 --- a/src/Hyperbee.Pipeline/Builders/WaitAllBlockBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/WaitAllBlockBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Context; using Hyperbee.Pipeline.Extensions.Implementation; @@ -97,9 +98,13 @@ public static IPipelineBuilder WaitAll( .Select( x => x.builder( x.block ).CastFunction() ) .ToArray(); + Expression> configExpression = config == null + ? null + : ctx => config( ctx ); + return new PipelineBuilder { - Function = new WaitAllBlockBinder( parentFunction, parentMiddleware, config ).Bind( functions, reducer ), + //Function = new WaitAllBlockBinder( parentFunction, parentMiddleware, configExpression ).Bind( functions, reducer ), Middleware = parentMiddleware }; } diff --git a/src/Hyperbee.Pipeline/Builders/WrapBuilder.cs b/src/Hyperbee.Pipeline/Builders/WrapBuilder.cs index d3b91fe..0c79129 100644 --- a/src/Hyperbee.Pipeline/Builders/WrapBuilder.cs +++ b/src/Hyperbee.Pipeline/Builders/WrapBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Binders; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Binders; using Hyperbee.Pipeline.Context; using Hyperbee.Pipeline.Extensions.Implementation; @@ -47,9 +48,16 @@ public static IPipelineBuilder WrapAsync( var (parentFunction, parentMiddleware) = parent.GetPipelineFunction(); + Expression> middlewareExpression = + (ctx, arg, function) => pipelineMiddleware( ctx, arg, function ); + + Expression> configExpression = config == null + ? null + : ctx => config( ctx ); + return new PipelineBuilder { - Function = new WrapBinder( pipelineMiddleware, config ).Bind( parentFunction ), + Function = new WrapBinder( middlewareExpression, configExpression ).Bind( parentFunction ), Middleware = parentMiddleware }; } diff --git a/src/Hyperbee.Pipeline/Hyperbee.Pipeline.csproj b/src/Hyperbee.Pipeline/Hyperbee.Pipeline.csproj index e4663d4..286d034 100644 --- a/src/Hyperbee.Pipeline/Hyperbee.Pipeline.csproj +++ b/src/Hyperbee.Pipeline/Hyperbee.Pipeline.csproj @@ -30,7 +30,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + \ No newline at end of file diff --git a/src/Hyperbee.Pipeline/IPipelineBuilder.cs b/src/Hyperbee.Pipeline/IPipelineBuilder.cs index 86b2c1c..7d50d8b 100644 --- a/src/Hyperbee.Pipeline/IPipelineBuilder.cs +++ b/src/Hyperbee.Pipeline/IPipelineBuilder.cs @@ -1,4 +1,5 @@ -using Hyperbee.Pipeline.Context; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Context; namespace Hyperbee.Pipeline; @@ -57,4 +58,5 @@ public interface IPipelineBuilder // used to bind the tail of an inner builder to the continuation of its parent. // this is necessary because you can't directly cast delegates. FunctionAsync CastFunction(); + Expression> CastExpression(); } diff --git a/src/Hyperbee.Pipeline/IPipelineFunction.cs b/src/Hyperbee.Pipeline/IPipelineFunction.cs index e4b6b04..3225b19 100644 --- a/src/Hyperbee.Pipeline/IPipelineFunction.cs +++ b/src/Hyperbee.Pipeline/IPipelineFunction.cs @@ -1,4 +1,6 @@ -namespace Hyperbee.Pipeline; +using System.Linq.Expressions; + +namespace Hyperbee.Pipeline; public interface IPipelineFunctionProvider { @@ -9,10 +11,10 @@ public interface IPipelineFunctionProvider public interface IPipelineFunction { - FunctionAsync Function { get; } - MiddlewareAsync Middleware { get; } + Expression> Function { get; } + Expression> Middleware { get; } - void Deconstruct( out FunctionAsync function, out MiddlewareAsync middleware ) + void Deconstruct( out Expression> function, out Expression> middleware ) { function = Function; middleware = Middleware; diff --git a/src/Hyperbee.Pipeline/PipelineBuilder.cs b/src/Hyperbee.Pipeline/PipelineBuilder.cs index 2dfe12d..1d933da 100644 --- a/src/Hyperbee.Pipeline/PipelineBuilder.cs +++ b/src/Hyperbee.Pipeline/PipelineBuilder.cs @@ -1,11 +1,15 @@ -using Hyperbee.Pipeline.Data; +using System.Linq.Expressions; +using Hyperbee.Pipeline.Context; +using Hyperbee.Pipeline.Data; +using static System.Linq.Expressions.Expression; +using static Hyperbee.Expressions.AsyncExpression; namespace Hyperbee.Pipeline; public class PipelineBuilder : PipelineFactory, IPipelineStartBuilder, IPipelineFunctionProvider { - internal FunctionAsync Function { get; init; } - internal MiddlewareAsync Middleware { get; init; } + internal Expression> Function { get; init; } + internal Expression> Middleware { get; init; } internal PipelineBuilder() { @@ -14,11 +18,14 @@ internal PipelineBuilder() public FunctionAsync Build() { // build and return the outermost method + + var compiledFunction = Function.Compile(); + return async ( context, argument ) => { try { - var result = await Function( context, argument ).ConfigureAwait( false ); + var result = await compiledFunction( context, argument ).ConfigureAwait( false ); if ( context.CancellationToken.IsCancellationRequested ) return Converter.TryConvertTo( context.CancellationValue, out var converted ) ? converted : default; @@ -40,11 +47,13 @@ public FunctionAsync Build() public ProcedureAsync BuildAsProcedure() { // build and return the outermost method + var compiledFunction = Function.Compile(); + return async ( context, argument ) => { try { - await Function( context, argument ).ConfigureAwait( false ); + await compiledFunction( context, argument ).ConfigureAwait( false ); } catch ( Exception ex ) { @@ -58,15 +67,31 @@ public ProcedureAsync BuildAsProcedure() FunctionAsync IPipelineBuilder.CastFunction() { + var compiledFunction = Function.Compile(); + return async ( context, argument ) => { - var result = await Function( context, Cast( argument ) ).ConfigureAwait( false ); + var result = await compiledFunction( context, Cast( argument ) ).ConfigureAwait( false ); return Cast( result ); }; static TType Cast( object value ) => (TType) value; } + Expression> IPipelineBuilder.CastExpression() + { + var context = Parameter( typeof( IPipelineContext ), "context" ); + var argument = Parameter( typeof( TInput ), "argument" ); + + return Lambda>( + BlockAsync( + [context, argument], + Convert( Await( Invoke( Function, context, Convert( argument, typeof( TInput ) ) ), configureAwait: false ), typeof( TOut ) ) + ), + parameters: [context, argument] + ); + } + // custom builders and binders need access to Function and Middleware IPipelineFunction IPipelineFunctionProvider.GetPipelineFunction() { @@ -79,7 +104,7 @@ IPipelineFunction IPipelineFunctionProvider.Ge public record PipelineFunction : IPipelineFunction { - public FunctionAsync Function { get; init; } - public MiddlewareAsync Middleware { get; init; } + public Expression> Function { get; init; } + public Expression> Middleware { get; init; } } } diff --git a/src/Hyperbee.Pipeline/PipelineFactory.cs b/src/Hyperbee.Pipeline/PipelineFactory.cs index 578dfd1..a97e9ec 100644 --- a/src/Hyperbee.Pipeline/PipelineFactory.cs +++ b/src/Hyperbee.Pipeline/PipelineFactory.cs @@ -1,4 +1,6 @@ -namespace Hyperbee.Pipeline; +using System.Linq.Expressions; + +namespace Hyperbee.Pipeline; // A quick note about generic arguments. Remember that the builder methods are // forward-looking and are always building the 'next' step. @@ -30,7 +32,7 @@ public static IPipelineStartBuilder Start() }; } - internal static IPipelineStartBuilder Start( MiddlewareAsync functionMiddleware ) + internal static IPipelineStartBuilder Start( Expression> functionMiddleware ) { return new PipelineBuilder { diff --git a/src/Hyperbee.Pipline.Caching/Hyperbee.Pipeline.Caching.csproj b/src/Hyperbee.Pipline.Caching/Hyperbee.Pipeline.Caching.csproj index 746088f..ef35005 100644 --- a/src/Hyperbee.Pipline.Caching/Hyperbee.Pipeline.Caching.csproj +++ b/src/Hyperbee.Pipline.Caching/Hyperbee.Pipeline.Caching.csproj @@ -39,7 +39,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/Hyperbee.Pipline.Caching/PipelineDistributedCacheExtensions.cs b/src/Hyperbee.Pipline.Caching/PipelineDistributedCacheExtensions.cs index 6fd61ee..07db1e3 100644 --- a/src/Hyperbee.Pipline.Caching/PipelineDistributedCacheExtensions.cs +++ b/src/Hyperbee.Pipline.Caching/PipelineDistributedCacheExtensions.cs @@ -18,7 +18,8 @@ public static IPipelineBuilder PipeDistributedCacheAsync(); var function = nestedBuilder( block ).GetPipelineFunction(); - return builder.PipeDistributedCacheAsync( function.Function, optionsFunc ); + // TODO: implement this + return null; // builder.PipeDistributedCacheAsync( function.Function, optionsFunc ); } public static IPipelineBuilder PipeDistributedCacheAsync( diff --git a/src/Hyperbee.Pipline.Caching/PipelineMemoryCacheExtensions.cs b/src/Hyperbee.Pipline.Caching/PipelineMemoryCacheExtensions.cs index ab19f2e..b151e74 100644 --- a/src/Hyperbee.Pipline.Caching/PipelineMemoryCacheExtensions.cs +++ b/src/Hyperbee.Pipline.Caching/PipelineMemoryCacheExtensions.cs @@ -18,7 +18,8 @@ public static IPipelineBuilder PipeCache( var block = PipelineFactory.Start(); var function = nestedBuilder( block ).GetPipelineFunction(); - return builder.PipeCacheAsync( function.Function, optionsFunc ); + // TODO: implement this + return null; //return builder.PipeCacheAsync( function.Function, optionsFunc ); } public static IPipelineBuilder PipeCacheAsync( @@ -31,7 +32,8 @@ public static IPipelineBuilder PipeCacheAsync(); var function = nestedBuilder( block ).GetPipelineFunction(); - return builder.PipeCacheAsync( function.Function, optionsFunc ); + // TODO: implement this + return null; // return builder.PipeCacheAsync( function.Function, optionsFunc ); } public static IPipelineBuilder PipeCache( diff --git a/test/Hyperbee.Pipeline.Auth.Tests/Hyperbee.Pipeline.Auth.Tests.csproj b/test/Hyperbee.Pipeline.Auth.Tests/Hyperbee.Pipeline.Auth.Tests.csproj index 41362a1..67d34b5 100644 --- a/test/Hyperbee.Pipeline.Auth.Tests/Hyperbee.Pipeline.Auth.Tests.csproj +++ b/test/Hyperbee.Pipeline.Auth.Tests/Hyperbee.Pipeline.Auth.Tests.csproj @@ -13,9 +13,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + diff --git a/test/Hyperbee.Pipeline.Tests/Hyperbee.Pipeline.Tests.csproj b/test/Hyperbee.Pipeline.Tests/Hyperbee.Pipeline.Tests.csproj index e5c9897..a5a66b2 100644 --- a/test/Hyperbee.Pipeline.Tests/Hyperbee.Pipeline.Tests.csproj +++ b/test/Hyperbee.Pipeline.Tests/Hyperbee.Pipeline.Tests.csproj @@ -4,9 +4,9 @@ false - - - + + + diff --git a/test/Hyperbee.PipelineCaching.Tests/Hyperbee.Pipeline.Caching.Tests.csproj b/test/Hyperbee.PipelineCaching.Tests/Hyperbee.Pipeline.Caching.Tests.csproj index 1f5d1bb..b07f8af 100644 --- a/test/Hyperbee.PipelineCaching.Tests/Hyperbee.Pipeline.Caching.Tests.csproj +++ b/test/Hyperbee.PipelineCaching.Tests/Hyperbee.Pipeline.Caching.Tests.csproj @@ -13,10 +13,10 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + +