From 7ed10eef90dd6eb6275ebdd7718a82674677b184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 18:25:52 +0200 Subject: [PATCH 01/12] replace IsDisposable with Dispose --- ...tivatorUtilitiesMiddlewareResolverTests.cs | 10 ++--- .../ServiceProviderMiddlewareResolverTests.cs | 10 ++--- .../ActivatorUtilitiesMiddlewareResolver.cs | 8 +--- .../ServiceProviderMiddlewareResolver.cs | 4 +- .../AsyncResponsibilityChain.cs | 30 +------------ .../ResponsibilityChain.cs | 44 +++++++------------ .../ActivatorMiddlewareResolver.cs | 8 +--- .../MiddlewareResolverResult.cs | 7 ++- src/PipelineNet/Pipelines/AsyncPipeline.cs | 15 +------ src/PipelineNet/Pipelines/Pipeline.cs | 22 ++++------ 10 files changed, 46 insertions(+), 112 deletions(-) diff --git a/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolverTests.cs b/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolverTests.cs index 4329c26..2ec6bd2 100644 --- a/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolverTests.cs +++ b/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolverTests.cs @@ -125,7 +125,7 @@ public void Resolve_ResolvesParameterlessConstructorMiddleware() var resolverResult = resolver.Resolve(typeof(ParameterlessConstructorMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.True(resolverResult.Dispose); } [Fact] @@ -139,7 +139,7 @@ public void Resolve_ResolvesTransientMiddleware() var resolverResult = resolver.Resolve(typeof(TransientMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.True(resolverResult.Dispose); } [Fact] @@ -154,7 +154,7 @@ public void Resolve_ResolvesScopedMiddleware() var resolverResult = resolver.Resolve(typeof(ScopedMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.True(resolverResult.Dispose); } [Fact] @@ -168,7 +168,7 @@ public void Resolve_ResolvesSingletonMiddleware() var resolverResult = resolver.Resolve(typeof(SingletonMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.True(resolverResult.Dispose); } [Fact] @@ -182,7 +182,7 @@ public void Resolve_ResolvesDisposableMiddleware() var resolverResult = resolver.Resolve(typeof(DisposableMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.True(resolverResult.IsDisposable); + Assert.True(resolverResult.Dispose); } [Fact] diff --git a/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ServiceProviderMiddlewareResolverTests.cs b/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ServiceProviderMiddlewareResolverTests.cs index 587f2e8..9655f5c 100644 --- a/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ServiceProviderMiddlewareResolverTests.cs +++ b/src/PipelineNet.ServiceProvider.Tests/MiddlewareResolver/ServiceProviderMiddlewareResolverTests.cs @@ -105,7 +105,7 @@ public void Resolve_ResolvesParameterlessConstructorMiddleware() var resolverResult = resolver.Resolve(typeof(ParameterlessConstructorMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.False(resolverResult.Dispose); } [Fact] @@ -120,7 +120,7 @@ public void Resolve_ResolvesTransientMiddleware() var resolverResult = resolver.Resolve(typeof(TransientMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.False(resolverResult.Dispose); } [Fact] @@ -136,7 +136,7 @@ public void Resolve_ResolvesScopedMiddleware() var resolverResult = resolver.Resolve(typeof(ScopedMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.False(resolverResult.Dispose); } [Fact] @@ -151,7 +151,7 @@ public void Resolve_ResolvesSingletonMiddleware() var resolverResult = resolver.Resolve(typeof(SingletonMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.False(resolverResult.Dispose); } [Fact] @@ -166,7 +166,7 @@ public void Resolve_ResolvesDisposableMiddleware() var resolverResult = resolver.Resolve(typeof(DisposableMiddleware)); Assert.NotNull(resolverResult.Middleware); - Assert.False(resolverResult.IsDisposable); + Assert.False(resolverResult.Dispose); } [Fact] diff --git a/src/PipelineNet.ServiceProvider/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolver.cs b/src/PipelineNet.ServiceProvider/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolver.cs index 183c05d..9b843f5 100644 --- a/src/PipelineNet.ServiceProvider/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolver.cs +++ b/src/PipelineNet.ServiceProvider/MiddlewareResolver/ActivatorUtilitiesMiddlewareResolver.cs @@ -26,16 +26,12 @@ public ActivatorUtilitiesMiddlewareResolver(IServiceProvider serviceProvider) public MiddlewareResolverResult Resolve(Type type) { var middleware = ActivatorUtilities.CreateInstance(_serviceProvider, type); - bool isDisposable = middleware is IDisposable -#if NETSTANDARD2_1_OR_GREATER - || middleware is IAsyncDisposable -#endif - ; + bool dispose = true; return new MiddlewareResolverResult() { Middleware = middleware, - IsDisposable = isDisposable + Dispose = dispose }; } } diff --git a/src/PipelineNet.ServiceProvider/MiddlewareResolver/ServiceProviderMiddlewareResolver.cs b/src/PipelineNet.ServiceProvider/MiddlewareResolver/ServiceProviderMiddlewareResolver.cs index 9c2f8ed..b0beeab 100644 --- a/src/PipelineNet.ServiceProvider/MiddlewareResolver/ServiceProviderMiddlewareResolver.cs +++ b/src/PipelineNet.ServiceProvider/MiddlewareResolver/ServiceProviderMiddlewareResolver.cs @@ -30,12 +30,12 @@ public ServiceProviderMiddlewareResolver(IServiceProvider serviceProvider) public MiddlewareResolverResult Resolve(Type type) { var middleware = _serviceProvider.GetRequiredService(type); - bool isDisposable = false; + bool dispose = false; return new MiddlewareResolverResult() { Middleware = middleware, - IsDisposable = isDisposable + Dispose = dispose }; } } diff --git a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs index d6cfb58..9614c4a 100644 --- a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs @@ -120,19 +120,6 @@ public async Task Execute(TParameter parameter, CancellationToken cance throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve finally of type '{_finallyType}'."); } - if (finallyResolverResult.IsDisposable && !(finallyResolverResult.Middleware is IDisposable -#if NETSTANDARD2_1_OR_GREATER - || finallyResolverResult.Middleware is IAsyncDisposable -#endif - )) - { - throw new InvalidOperationException($"'{finallyResolverResult.Middleware.GetType()}' type does not implement IDisposable" + -#if NETSTANDARD2_1_OR_GREATER - " or IAsyncDisposable" + -#endif - "."); - } - if (finallyResolverResult.Middleware is ICancellableAsyncFinally cancellableFinally) { func = async (p) => await cancellableFinally.Finally(p, cancellationToken).ConfigureAwait(false); @@ -158,19 +145,6 @@ public async Task Execute(TParameter parameter, CancellationToken cance throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); } - if (resolverResult.IsDisposable && !(resolverResult.Middleware is IDisposable -#if NETSTANDARD2_1_OR_GREATER - || resolverResult.Middleware is IAsyncDisposable -#endif - )) - { - throw new InvalidOperationException($"'{resolverResult.Middleware.GetType()}' type does not implement IDisposable" + -#if NETSTANDARD2_1_OR_GREATER - " or IAsyncDisposable" + -#endif - "."); - } - if (resolverResult.Middleware is ICancellableAsyncMiddleware cancellableMiddleware) { return await cancellableMiddleware.Run(param, func, cancellationToken).ConfigureAwait(false); @@ -183,7 +157,7 @@ public async Task Execute(TParameter parameter, CancellationToken cance } finally { - if (resolverResult != null && resolverResult.IsDisposable) + if (resolverResult != null && resolverResult.Dispose) { var middleware = resolverResult.Middleware; if (middleware != null) @@ -202,7 +176,7 @@ public async Task Execute(TParameter parameter, CancellationToken cance } } - if (finallyResolverResult != null && finallyResolverResult.IsDisposable) + if (finallyResolverResult != null && finallyResolverResult.Dispose) { var @finally = finallyResolverResult.Middleware; if (@finally != null) diff --git a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs index 4067e28..46e9396 100644 --- a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs @@ -138,19 +138,6 @@ public TReturn Execute(TParameter parameter) throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve finally of type '{_finallyType}'."); } - if (finallyResolverResult.IsDisposable && !(finallyResolverResult.Middleware is IDisposable)) - { -#if NETSTANDARD2_1_OR_GREATER - if (finallyResolverResult.Middleware is IAsyncDisposable) - { - throw new InvalidOperationException($"'{finallyResolverResult.Middleware.GetType()}' type only implements IAsyncDisposable." + - " Use AsyncResponsibilityChain to execute the configured pipeline."); - } -#endif - - throw new InvalidOperationException($"'{finallyResolverResult.Middleware.GetType()}' type does not implement IDisposable."); - } - var @finally = (IFinally)finallyResolverResult.Middleware; func = (p) => @finally.Finally(p); } @@ -169,25 +156,12 @@ public TReturn Execute(TParameter parameter) throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); } - if (resolverResult.IsDisposable && !(resolverResult.Middleware is IDisposable)) - { -#if NETSTANDARD2_1_OR_GREATER - if (resolverResult.Middleware is IAsyncDisposable) - { - throw new InvalidOperationException($"'{resolverResult.Middleware.GetType()}' type only implements IAsyncDisposable." + - " Use AsyncResponsibilityChain to execute the configured pipeline."); - } -#endif - - throw new InvalidOperationException($"'{resolverResult.Middleware.GetType()}' type does not implement IDisposable."); - } - var middleware = (IMiddleware)resolverResult.Middleware; return middleware.Run(param, func); } finally { - if (resolverResult != null && resolverResult.IsDisposable) + if (resolverResult != null && resolverResult.Dispose) { var middleware = resolverResult.Middleware; if (middleware != null) @@ -196,10 +170,17 @@ public TReturn Execute(TParameter parameter) { disposable.Dispose(); } +#if NETSTANDARD2_1_OR_GREATER + else if (middleware is IAsyncDisposable) + { + throw new InvalidOperationException($"'{middleware.GetType()}' type only implements IAsyncDisposable." + + " Use AsyncResponsibilityChain to execute the configured pipeline."); + } +#endif } } - if (finallyResolverResult != null && finallyResolverResult.IsDisposable) + if (finallyResolverResult != null && finallyResolverResult.Dispose) { var @finally = finallyResolverResult.Middleware; if (@finally != null) @@ -208,6 +189,13 @@ public TReturn Execute(TParameter parameter) { disposable.Dispose(); } +#if NETSTANDARD2_1_OR_GREATER + else if (@finally is IAsyncDisposable) + { + throw new InvalidOperationException($"'{@finally.GetType()}' type only implements IAsyncDisposable." + + " Use AsyncResponsibilityChain to execute the configured pipeline."); + } +#endif } } } diff --git a/src/PipelineNet/MiddlewareResolver/ActivatorMiddlewareResolver.cs b/src/PipelineNet/MiddlewareResolver/ActivatorMiddlewareResolver.cs index f9345dd..ba31896 100644 --- a/src/PipelineNet/MiddlewareResolver/ActivatorMiddlewareResolver.cs +++ b/src/PipelineNet/MiddlewareResolver/ActivatorMiddlewareResolver.cs @@ -12,16 +12,12 @@ public class ActivatorMiddlewareResolver : IMiddlewareResolver public MiddlewareResolverResult Resolve(Type type) { var middleware = Activator.CreateInstance(type); - bool isDisposable = middleware is IDisposable -#if NETSTANDARD2_1_OR_GREATER - || middleware is IAsyncDisposable -#endif - ; + bool dispose = true; return new MiddlewareResolverResult() { Middleware = middleware, - IsDisposable = isDisposable + Dispose = dispose }; } } diff --git a/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs b/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs index 85b42f2..b7c5a3b 100644 --- a/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs +++ b/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs @@ -12,10 +12,9 @@ public class MiddlewareResolverResult /// /// Gets or sets the value indicating whether the middleware should be disposed. - /// Set this to if the middleware is IDisposable or - /// IAsyncDisposable (requires .NET Standard 2.1 or greater) - /// and is not disposed by a dependency injection container. + /// Set this to if the middleware is not disposed + /// by a dependency injection container. /// - public bool IsDisposable { get; set; } + public bool Dispose { get; set; } } } diff --git a/src/PipelineNet/Pipelines/AsyncPipeline.cs b/src/PipelineNet/Pipelines/AsyncPipeline.cs index 83fd65b..c9a2308 100644 --- a/src/PipelineNet/Pipelines/AsyncPipeline.cs +++ b/src/PipelineNet/Pipelines/AsyncPipeline.cs @@ -94,19 +94,6 @@ public async Task Execute(TParameter parameter, CancellationToken cancellationTo throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); } - if (resolverResult.IsDisposable && !(resolverResult.Middleware is IDisposable -#if NETSTANDARD2_1_OR_GREATER - || resolverResult.Middleware is IAsyncDisposable -#endif - )) - { - throw new InvalidOperationException($"'{resolverResult.Middleware.GetType()}' type does not implement IDisposable" + -#if NETSTANDARD2_1_OR_GREATER - " or IAsyncDisposable" + -#endif - "."); - } - if (resolverResult.Middleware is ICancellableAsyncMiddleware cancellableMiddleware) { await cancellableMiddleware.Run(param, action, cancellationToken).ConfigureAwait(false); @@ -119,7 +106,7 @@ public async Task Execute(TParameter parameter, CancellationToken cancellationTo } finally { - if (resolverResult != null && resolverResult.IsDisposable) + if (resolverResult != null && resolverResult.Dispose) { var middleware = resolverResult.Middleware; if (middleware != null) diff --git a/src/PipelineNet/Pipelines/Pipeline.cs b/src/PipelineNet/Pipelines/Pipeline.cs index 30100ec..6ff5696 100644 --- a/src/PipelineNet/Pipelines/Pipeline.cs +++ b/src/PipelineNet/Pipelines/Pipeline.cs @@ -72,25 +72,12 @@ public void Execute(TParameter parameter) throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); } - if (resolverResult.IsDisposable && !(resolverResult.Middleware is IDisposable)) - { -#if NETSTANDARD2_1_OR_GREATER - if (resolverResult.Middleware is IAsyncDisposable) - { - throw new InvalidOperationException($"'{resolverResult.Middleware.GetType()}' type only implements IAsyncDisposable." + - " Use AsyncPipeline to execute the configured pipeline."); - } -#endif - - throw new InvalidOperationException($"'{resolverResult.Middleware.GetType()}' type does not implement IDisposable."); - } - var middleware = (IMiddleware)resolverResult.Middleware; middleware.Run(param, action); } finally { - if (resolverResult != null && resolverResult.IsDisposable) + if (resolverResult != null && resolverResult.Dispose) { var middleware = resolverResult.Middleware; if (middleware != null) @@ -99,6 +86,13 @@ public void Execute(TParameter parameter) { disposable.Dispose(); } +#if NETSTANDARD2_1_OR_GREATER + else if (middleware is IAsyncDisposable) + { + throw new InvalidOperationException($"'{middleware.GetType()}' type only implements IAsyncDisposable." + + " Use AsyncPipeline to execute the configured pipeline."); + } +#endif } } } From 931f79fd03695769f813e965856182b22a29a714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 18:27:51 +0200 Subject: [PATCH 02/12] don't check the type of TFinally twice --- .../AsyncResponsibilityChain.cs | 14 ++++++++++---- .../ChainsOfResponsibility/ResponsibilityChain.cs | 7 +++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs index 9614c4a..94b3e49 100644 --- a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs @@ -208,8 +208,11 @@ public async Task Execute(TParameter parameter, CancellationToken cance /// The finally being set. /// The current instance of . public IAsyncResponsibilityChain Finally() - where TFinally : IAsyncFinally => - Finally(typeof(TFinally)); + where TFinally : IAsyncFinally + { + _finallyType = typeof(TFinally); + return this; + } /// /// Sets the cancellable finally to be executed at the end of the chain as a fallback. @@ -219,8 +222,11 @@ public IAsyncResponsibilityChain Finally() /// The cancellable finally being set. /// The current instance of . public IAsyncResponsibilityChain CancellableFinally() - where TCancellableFinally : ICancellableAsyncFinally => - Finally(typeof(TCancellableFinally)); + where TCancellableFinally : ICancellableAsyncFinally + { + _finallyType = typeof(TCancellableFinally); + return this; + } /// /// Sets the finally to be executed at the end of the chain as a fallback. diff --git a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs index 46e9396..49acb3e 100644 --- a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs @@ -38,8 +38,11 @@ public ResponsibilityChain(IMiddlewareResolver middlewareResolver) : base(middle /// The finally being set. /// The current instance of . public IResponsibilityChain Finally() - where TFinally : IFinally => - Finally(typeof(TFinally)); + where TFinally : IFinally + { + _finallyType = typeof(TFinally); + return this; + } /// /// Sets the finally to be executed at the end of the chain as a fallback. From e3c08c02ecc51f1a1d45ede06c1292f82b39e7c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 19:08:34 +0200 Subject: [PATCH 03/12] extract methods --- src/PipelineNet/AsyncBaseMiddlewareFlow.cs | 34 +++++- src/PipelineNet/BaseMiddlewareFlow.cs | 30 +++++ .../AsyncResponsibilityChain.cs | 107 +++++++----------- .../ResponsibilityChain.cs | 70 +++--------- src/PipelineNet/Pipelines/AsyncPipeline.cs | 54 ++++----- src/PipelineNet/Pipelines/Pipeline.cs | 34 ++---- 6 files changed, 151 insertions(+), 178 deletions(-) diff --git a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs index 2c4bf6b..1db9a3e 100644 --- a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs +++ b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Threading.Tasks; namespace PipelineNet { @@ -46,7 +47,7 @@ internal AsyncBaseMiddlewareFlow(IMiddlewareResolver middlewareResolver) /// /// The middleware type to be executed. /// Thrown if the is - /// not an implementation of or . + /// not an implementation of or . /// Thrown if is null. protected void AddMiddleware(Type middlewareType) { @@ -60,5 +61,36 @@ protected void AddMiddleware(Type middlewareType) this.MiddlewareTypes.Add(middlewareType); } + + internal void EnsureMiddlewareNotNull(MiddlewareResolverResult middlewareResolverResult, Type middlewareType) + { + if (middlewareResolverResult == null || middlewareResolverResult.Middleware == null) + { + throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{middlewareType}'."); + } + } + + internal static async Task DisposeMiddlewareAsync(MiddlewareResolverResult middlewareResolverResult) + { + if (middlewareResolverResult != null && middlewareResolverResult.Dispose) + { + var middleware = middlewareResolverResult.Middleware; + if (middleware != null) + { +#if NETSTANDARD2_1_OR_GREATER + if (middleware is IAsyncDisposable asyncDisposable) + { + await asyncDisposable.DisposeAsync().ConfigureAwait(false); + } +#else + await Task.FromResult(default(int)).ConfigureAwait(false); +#endif + if (middleware is IDisposable disposable) + { + disposable.Dispose(); + } + } + } + } } } diff --git a/src/PipelineNet/BaseMiddlewareFlow.cs b/src/PipelineNet/BaseMiddlewareFlow.cs index e465e56..7de3c98 100644 --- a/src/PipelineNet/BaseMiddlewareFlow.cs +++ b/src/PipelineNet/BaseMiddlewareFlow.cs @@ -52,5 +52,35 @@ protected void AddMiddleware(Type middlewareType) this.MiddlewareTypes.Add(middlewareType); } + + internal void EnsureMiddlewareNotNull(MiddlewareResolverResult middlewareResolverResult, Type middlewareType) + { + if (middlewareResolverResult == null || middlewareResolverResult.Middleware == null) + { + throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{middlewareType}'."); + } + } + + internal static void DisposeMiddleware(MiddlewareResolverResult middlewareResolverResult) + { + if (middlewareResolverResult != null && middlewareResolverResult.Dispose) + { + var middleware = middlewareResolverResult.Middleware; + if (middleware != null) + { + if (middleware is IDisposable disposable) + { + disposable.Dispose(); + } +#if NETSTANDARD2_1_OR_GREATER + else if (middleware is IAsyncDisposable) + { + throw new InvalidOperationException($"'{middleware.GetType()}' type only implements IAsyncDisposable." + + " Use AsyncPipeline/AsyncResponsibilityChain to execute the configured pipeline/chain fo responsibility."); + } +#endif + } + } + } } } diff --git a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs index 94b3e49..65afa2d 100644 --- a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs @@ -114,21 +114,8 @@ public async Task Execute(TParameter parameter, CancellationToken cance if (_finallyType != null) { finallyResolverResult = MiddlewareResolver.Resolve(_finallyType); - - if (finallyResolverResult == null || finallyResolverResult.Middleware == null) - { - throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve finally of type '{_finallyType}'."); - } - - if (finallyResolverResult.Middleware is ICancellableAsyncFinally cancellableFinally) - { - func = async (p) => await cancellableFinally.Finally(p, cancellationToken).ConfigureAwait(false); - } - else - { - var @finally = (IAsyncFinally)finallyResolverResult.Middleware; - func = async (p) => await @finally.Finally(p).ConfigureAwait(false); - } + EnsureMiddlewareNotNull(finallyResolverResult, _finallyType); + func = async (p) => await RunFinallyAsync(finallyResolverResult, p, cancellationToken).ConfigureAwait(false); } else if (_finallyFunc != null) { @@ -136,70 +123,56 @@ public async Task Execute(TParameter parameter, CancellationToken cance } else { - func = (p) => Task.FromResult(default(TReturn)); + func = async (p) => await Task.FromResult(default(TReturn)).ConfigureAwait(false); } } - if (resolverResult == null || resolverResult.Middleware == null) - { - throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); - } - - if (resolverResult.Middleware is ICancellableAsyncMiddleware cancellableMiddleware) - { - return await cancellableMiddleware.Run(param, func, cancellationToken).ConfigureAwait(false); - } - else - { - var middleware = (IAsyncMiddleware)resolverResult.Middleware; - return await middleware.Run(param, func).ConfigureAwait(false); - } + EnsureMiddlewareNotNull(resolverResult, type); + return await RunMiddlewareAsync(resolverResult, param, func, cancellationToken).ConfigureAwait(false); } finally { - if (resolverResult != null && resolverResult.Dispose) - { - var middleware = resolverResult.Middleware; - if (middleware != null) - { -#if NETSTANDARD2_1_OR_GREATER - if (middleware is IAsyncDisposable asyncDisposable) - { - await asyncDisposable.DisposeAsync().ConfigureAwait(false); - } - else -#endif - if (middleware is IDisposable disposable) - { - disposable.Dispose(); - } - } - } - - if (finallyResolverResult != null && finallyResolverResult.Dispose) - { - var @finally = finallyResolverResult.Middleware; - if (@finally != null) - { -#if NETSTANDARD2_1_OR_GREATER - if (@finally is IAsyncDisposable asyncDisposable) - { - await asyncDisposable.DisposeAsync().ConfigureAwait(false); - } - else -#endif - if (@finally is IDisposable disposable) - { - disposable.Dispose(); - } - } - } + await DisposeMiddlewareAsync(resolverResult).ConfigureAwait(false); + await DisposeMiddlewareAsync(finallyResolverResult).ConfigureAwait(false); } }; return await func(parameter).ConfigureAwait(false); } + private static async Task RunMiddlewareAsync( + MiddlewareResolverResult middlewareResolverResult, + TParameter parameter, + Func> next, + CancellationToken cancellationToken) + { + if (middlewareResolverResult.Middleware is ICancellableAsyncMiddleware cancellableMiddleware) + { + return await cancellableMiddleware.Run(parameter, next, cancellationToken).ConfigureAwait(false); + } + else + { + var middleware = (IAsyncMiddleware)middlewareResolverResult.Middleware; + return await middleware.Run(parameter, next).ConfigureAwait(false); + } + } + + private static async Task RunFinallyAsync( + MiddlewareResolverResult finallyResolverResult, + TParameter parameter, + CancellationToken cancellationToken) + { + if (finallyResolverResult.Middleware is ICancellableAsyncFinally cancellableFinally) + { + return await cancellableFinally.Finally(parameter, cancellationToken).ConfigureAwait(false); + } + else + { + var @finally = (IAsyncFinally)finallyResolverResult.Middleware; + return await @finally.Finally(parameter).ConfigureAwait(false); + } + } + /// /// Sets the finally to be executed at the end of the chain as a fallback. /// A chain can only have one finally type. Calling this method more diff --git a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs index 49acb3e..4c5c815 100644 --- a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs @@ -135,14 +135,8 @@ public TReturn Execute(TParameter parameter) if (_finallyType != null) { finallyResolverResult = MiddlewareResolver.Resolve(_finallyType); - - if (finallyResolverResult == null || finallyResolverResult.Middleware == null) - { - throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve finally of type '{_finallyType}'."); - } - - var @finally = (IFinally)finallyResolverResult.Middleware; - func = (p) => @finally.Finally(p); + EnsureMiddlewareNotNull(finallyResolverResult, _finallyType); + func = (p) => RunFinally(finallyResolverResult, p); } else if (_finallyFunc != null) { @@ -154,57 +148,29 @@ public TReturn Execute(TParameter parameter) } } - if (resolverResult == null || resolverResult.Middleware == null) - { - throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); - } - - var middleware = (IMiddleware)resolverResult.Middleware; - return middleware.Run(param, func); + EnsureMiddlewareNotNull(resolverResult, type); + return RunMiddleware(resolverResult, param, func); } finally { - if (resolverResult != null && resolverResult.Dispose) - { - var middleware = resolverResult.Middleware; - if (middleware != null) - { - if (middleware is IDisposable disposable) - { - disposable.Dispose(); - } -#if NETSTANDARD2_1_OR_GREATER - else if (middleware is IAsyncDisposable) - { - throw new InvalidOperationException($"'{middleware.GetType()}' type only implements IAsyncDisposable." + - " Use AsyncResponsibilityChain to execute the configured pipeline."); - } -#endif - } - } - - if (finallyResolverResult != null && finallyResolverResult.Dispose) - { - var @finally = finallyResolverResult.Middleware; - if (@finally != null) - { - if (@finally is IDisposable disposable) - { - disposable.Dispose(); - } -#if NETSTANDARD2_1_OR_GREATER - else if (@finally is IAsyncDisposable) - { - throw new InvalidOperationException($"'{@finally.GetType()}' type only implements IAsyncDisposable." + - " Use AsyncResponsibilityChain to execute the configured pipeline."); - } -#endif - } - } + DisposeMiddleware(resolverResult); + DisposeMiddleware(finallyResolverResult); } }; return func(parameter); } + + private static TReturn RunMiddleware(MiddlewareResolverResult middlewareResolverResult, TParameter parameter, Func next) + { + var middleware = (IMiddleware)middlewareResolverResult.Middleware; + return middleware.Run(parameter, next); + } + + private static TReturn RunFinally(MiddlewareResolverResult finallyResolverResult, TParameter parameter) + { + var @finally = (IFinally)finallyResolverResult.Middleware; + return @finally.Finally(parameter); + } } } diff --git a/src/PipelineNet/Pipelines/AsyncPipeline.cs b/src/PipelineNet/Pipelines/AsyncPipeline.cs index c9a2308..b31f170 100644 --- a/src/PipelineNet/Pipelines/AsyncPipeline.cs +++ b/src/PipelineNet/Pipelines/AsyncPipeline.cs @@ -87,47 +87,35 @@ public async Task Execute(TParameter parameter, CancellationToken cancellationTo index++; if (index == MiddlewareTypes.Count) - action = (p) => Task.FromResult(0); + action = async (p) => await Task.FromResult(default(int)).ConfigureAwait(false); - if (resolverResult == null || resolverResult.Middleware == null) - { - throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); - } - - if (resolverResult.Middleware is ICancellableAsyncMiddleware cancellableMiddleware) - { - await cancellableMiddleware.Run(param, action, cancellationToken).ConfigureAwait(false); - } - else - { - var middleware = (IAsyncMiddleware)resolverResult.Middleware; - await middleware.Run(param, action).ConfigureAwait(false); - } + EnsureMiddlewareNotNull(resolverResult, type); + await RunMiddlewareAsync(resolverResult, param, action, cancellationToken).ConfigureAwait(false); } finally { - if (resolverResult != null && resolverResult.Dispose) - { - var middleware = resolverResult.Middleware; - if (middleware != null) - { -#if NETSTANDARD2_1_OR_GREATER - if (middleware is IAsyncDisposable asyncDisposable) - { - await asyncDisposable.DisposeAsync().ConfigureAwait(false); - } - else -#endif - if (middleware is IDisposable disposable) - { - disposable.Dispose(); - } - } - } + await DisposeMiddlewareAsync(resolverResult).ConfigureAwait(false); } }; await action(parameter).ConfigureAwait(false); } + + private static async Task RunMiddlewareAsync( + MiddlewareResolverResult resolverResult, + TParameter parameter, + Func next, + CancellationToken cancellationToken) + { + if (resolverResult.Middleware is ICancellableAsyncMiddleware cancellableMiddleware) + { + await cancellableMiddleware.Run(parameter, next, cancellationToken).ConfigureAwait(false); + } + else + { + var middleware = (IAsyncMiddleware)resolverResult.Middleware; + await middleware.Run(parameter, next).ConfigureAwait(false); + } + } } } diff --git a/src/PipelineNet/Pipelines/Pipeline.cs b/src/PipelineNet/Pipelines/Pipeline.cs index 6ff5696..4f7810a 100644 --- a/src/PipelineNet/Pipelines/Pipeline.cs +++ b/src/PipelineNet/Pipelines/Pipeline.cs @@ -67,38 +67,22 @@ public void Execute(TParameter parameter) if (index == MiddlewareTypes.Count) action = (p) => { }; - if (resolverResult == null || resolverResult.Middleware == null) - { - throw new InvalidOperationException($"'{MiddlewareResolver.GetType()}' failed to resolve middleware of type '{type}'."); - } - - var middleware = (IMiddleware)resolverResult.Middleware; - middleware.Run(param, action); + EnsureMiddlewareNotNull(resolverResult, type); + RunMiddleware(resolverResult, param, action); } finally { - if (resolverResult != null && resolverResult.Dispose) - { - var middleware = resolverResult.Middleware; - if (middleware != null) - { - if (middleware is IDisposable disposable) - { - disposable.Dispose(); - } -#if NETSTANDARD2_1_OR_GREATER - else if (middleware is IAsyncDisposable) - { - throw new InvalidOperationException($"'{middleware.GetType()}' type only implements IAsyncDisposable." + - " Use AsyncPipeline to execute the configured pipeline."); - } -#endif - } - } + DisposeMiddleware(resolverResult); } }; action(parameter); } + + private static void RunMiddleware(MiddlewareResolverResult middlewareResolverResult, TParameter parameter, Action next) + { + var middleware = (IMiddleware)middlewareResolverResult.Middleware; + middleware.Run(parameter, next); + } } } From 25726722f93e78dd31051d20591458b13199245a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 19:13:25 +0200 Subject: [PATCH 04/12] update variable names --- .../AsyncResponsibilityChain.cs | 24 +++++++++---------- .../ResponsibilityChain.cs | 24 +++++++++---------- src/PipelineNet/Pipelines/AsyncPipeline.cs | 20 ++++++++-------- src/PipelineNet/Pipelines/Pipeline.cs | 20 ++++++++-------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs index 65afa2d..78ba345 100644 --- a/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/AsyncResponsibilityChain.cs @@ -95,15 +95,15 @@ public async Task Execute(TParameter parameter, CancellationToken cance return default(TReturn); int index = 0; - Func> func = null; - func = async (param) => + Func> next = null; + next = async (parameter2) => { - MiddlewareResolverResult resolverResult = null; + MiddlewareResolverResult middlewareResolverResult = null; MiddlewareResolverResult finallyResolverResult = null; try { - var type = MiddlewareTypes[index]; - resolverResult = MiddlewareResolver.Resolve(type); + var middlewaretype = MiddlewareTypes[index]; + middlewareResolverResult = MiddlewareResolver.Resolve(middlewaretype); index++; // If the current instance of middleware is the last one in the list, @@ -115,29 +115,29 @@ public async Task Execute(TParameter parameter, CancellationToken cance { finallyResolverResult = MiddlewareResolver.Resolve(_finallyType); EnsureMiddlewareNotNull(finallyResolverResult, _finallyType); - func = async (p) => await RunFinallyAsync(finallyResolverResult, p, cancellationToken).ConfigureAwait(false); + next = async (p) => await RunFinallyAsync(finallyResolverResult, p, cancellationToken).ConfigureAwait(false); } else if (_finallyFunc != null) { - func = _finallyFunc; + next = _finallyFunc; } else { - func = async (p) => await Task.FromResult(default(TReturn)).ConfigureAwait(false); + next = async (p) => await Task.FromResult(default(TReturn)).ConfigureAwait(false); } } - EnsureMiddlewareNotNull(resolverResult, type); - return await RunMiddlewareAsync(resolverResult, param, func, cancellationToken).ConfigureAwait(false); + EnsureMiddlewareNotNull(middlewareResolverResult, middlewaretype); + return await RunMiddlewareAsync(middlewareResolverResult, parameter2, next, cancellationToken).ConfigureAwait(false); } finally { - await DisposeMiddlewareAsync(resolverResult).ConfigureAwait(false); + await DisposeMiddlewareAsync(middlewareResolverResult).ConfigureAwait(false); await DisposeMiddlewareAsync(finallyResolverResult).ConfigureAwait(false); } }; - return await func(parameter).ConfigureAwait(false); + return await next(parameter).ConfigureAwait(false); } private static async Task RunMiddlewareAsync( diff --git a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs index 4c5c815..ee912d2 100644 --- a/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs +++ b/src/PipelineNet/ChainsOfResponsibility/ResponsibilityChain.cs @@ -116,15 +116,15 @@ public TReturn Execute(TParameter parameter) return default(TReturn); int index = 0; - Func func = null; - func = (param) => + Func next = null; + next = (parameter2) => { - MiddlewareResolverResult resolverResult = null; + MiddlewareResolverResult middlewareResolverResult = null; MiddlewareResolverResult finallyResolverResult = null; try { - var type = MiddlewareTypes[index]; - resolverResult = MiddlewareResolver.Resolve(type); + var middlewaretype = MiddlewareTypes[index]; + middlewareResolverResult = MiddlewareResolver.Resolve(middlewaretype); index++; // If the current instance of middleware is the last one in the list, @@ -136,29 +136,29 @@ public TReturn Execute(TParameter parameter) { finallyResolverResult = MiddlewareResolver.Resolve(_finallyType); EnsureMiddlewareNotNull(finallyResolverResult, _finallyType); - func = (p) => RunFinally(finallyResolverResult, p); + next = (p) => RunFinally(finallyResolverResult, p); } else if (_finallyFunc != null) { - func = _finallyFunc; + next = _finallyFunc; } else { - func = (p) => default(TReturn); + next = (p) => default(TReturn); } } - EnsureMiddlewareNotNull(resolverResult, type); - return RunMiddleware(resolverResult, param, func); + EnsureMiddlewareNotNull(middlewareResolverResult, middlewaretype); + return RunMiddleware(middlewareResolverResult, parameter2, next); } finally { - DisposeMiddleware(resolverResult); + DisposeMiddleware(middlewareResolverResult); DisposeMiddleware(finallyResolverResult); } }; - return func(parameter); + return next(parameter); } private static TReturn RunMiddleware(MiddlewareResolverResult middlewareResolverResult, TParameter parameter, Func next) diff --git a/src/PipelineNet/Pipelines/AsyncPipeline.cs b/src/PipelineNet/Pipelines/AsyncPipeline.cs index b31f170..2e72c49 100644 --- a/src/PipelineNet/Pipelines/AsyncPipeline.cs +++ b/src/PipelineNet/Pipelines/AsyncPipeline.cs @@ -76,29 +76,29 @@ public async Task Execute(TParameter parameter, CancellationToken cancellationTo return; int index = 0; - Func action = null; - action = async (param) => + Func next = null; + next = async (parameter2) => { - MiddlewareResolverResult resolverResult = null; + MiddlewareResolverResult middlewareResolverResult = null; try { - var type = MiddlewareTypes[index]; - resolverResult = MiddlewareResolver.Resolve(type); + var middlewareType = MiddlewareTypes[index]; + middlewareResolverResult = MiddlewareResolver.Resolve(middlewareType); index++; if (index == MiddlewareTypes.Count) - action = async (p) => await Task.FromResult(default(int)).ConfigureAwait(false); + next = async (p) => await Task.FromResult(default(int)).ConfigureAwait(false); - EnsureMiddlewareNotNull(resolverResult, type); - await RunMiddlewareAsync(resolverResult, param, action, cancellationToken).ConfigureAwait(false); + EnsureMiddlewareNotNull(middlewareResolverResult, middlewareType); + await RunMiddlewareAsync(middlewareResolverResult, parameter2, next, cancellationToken).ConfigureAwait(false); } finally { - await DisposeMiddlewareAsync(resolverResult).ConfigureAwait(false); + await DisposeMiddlewareAsync(middlewareResolverResult).ConfigureAwait(false); } }; - await action(parameter).ConfigureAwait(false); + await next(parameter).ConfigureAwait(false); } private static async Task RunMiddlewareAsync( diff --git a/src/PipelineNet/Pipelines/Pipeline.cs b/src/PipelineNet/Pipelines/Pipeline.cs index 4f7810a..da9f657 100644 --- a/src/PipelineNet/Pipelines/Pipeline.cs +++ b/src/PipelineNet/Pipelines/Pipeline.cs @@ -54,29 +54,29 @@ public void Execute(TParameter parameter) return; int index = 0; - Action action = null; - action = (param) => + Action next = null; + next = (parameter2) => { - MiddlewareResolverResult resolverResult = null; + MiddlewareResolverResult middlewareResolverResult = null; try { - var type = MiddlewareTypes[index]; - resolverResult = MiddlewareResolver.Resolve(type); + var middlewareType = MiddlewareTypes[index]; + middlewareResolverResult = MiddlewareResolver.Resolve(middlewareType); index++; if (index == MiddlewareTypes.Count) - action = (p) => { }; + next = (p) => { }; - EnsureMiddlewareNotNull(resolverResult, type); - RunMiddleware(resolverResult, param, action); + EnsureMiddlewareNotNull(middlewareResolverResult, middlewareType); + RunMiddleware(middlewareResolverResult, parameter2, next); } finally { - DisposeMiddleware(resolverResult); + DisposeMiddleware(middlewareResolverResult); } }; - action(parameter); + next(parameter); } private static void RunMiddleware(MiddlewareResolverResult middlewareResolverResult, TParameter parameter, Action next) From 1a80fe9c6ca50fd6300c2bd0451594c348856b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 19:20:45 +0200 Subject: [PATCH 05/12] udpate PipelineNet.ServiceProvider csproj --- .../PipelineNet.ServiceProvider.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PipelineNet.ServiceProvider/PipelineNet.ServiceProvider.csproj b/src/PipelineNet.ServiceProvider/PipelineNet.ServiceProvider.csproj index f9c094d..952c9e5 100644 --- a/src/PipelineNet.ServiceProvider/PipelineNet.ServiceProvider.csproj +++ b/src/PipelineNet.ServiceProvider/PipelineNet.ServiceProvider.csproj @@ -24,7 +24,7 @@ - + From 334eab85c56b6865a2197fff8e415dc147cd3718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 19:21:57 +0200 Subject: [PATCH 06/12] udpate readme --- README.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0fd3e39..2e1d4bd 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,9 @@ You can even define a fallback that will be executed after your entire chain: var exceptionHandlersChain = new ResponsibilityChain(new ActivatorMiddlewareResolver()) .Chain() // The order of middleware being chained matters .Chain() - .Finally(); + .Finally(); -public class FinallyDoSomething : IFinally +public class DoSomething : IFinally { public bool Finally(Exception parameter) { @@ -105,7 +105,7 @@ var result = exceptionHandlersChain.Execute(new InvalidOperationException()); // ``` The result will be true because of the type used in the `Finally` method. -You can also choose to throw an exception in the `Finally` method instead of returning a value: +You can also choose to throw an exception in the finally instead of returning a value: ```C# var exceptionHandlersChain = new ResponsibilityChain(new ActivatorMiddlewareResolver()) .Chain() @@ -234,27 +234,22 @@ var pipeline = new AsyncPipeline(new ActivatorMiddlewareResolver()) .Add() // You can mix both kinds of asynchronous middleware .AddCancellable(); -Bitmap image = (Bitmap) Image.FromFile("party-photo.png"); CancellationToken cancellationToken = CancellationToken.None; + +Bitmap image = (Bitmap) Image.FromFile("party-photo.png"); await pipeline.Execute(image, cancellationToken); public class RoudCornersCancellableAsyncMiddleware : ICancellableAsyncMiddleware { public async Task Run(Bitmap parameter, Func next, CancellationToken cancellationToken) - { - await RoundCournersAsync(parameter, cancellationToken); - await next(parameter); - } - - private async Task RoudCournersAsync(Bitmap bitmap, CancellationToken cancellationToken) { // Handle somehow - await Task.CompletedTask; + await next(parameter); } } ``` And to pass the cancellation token to your asynchronous chain of responsibility middleware, you can implement the `ICancellableAsyncMiddleware` interface -and pass the cancellation token argument to the `IAsynchChainOfResponsibility.Execute` method. +and pass the cancellation token argument to the `IAsynchChainOfResponsibility.Execute` method. ## Middleware resolver You may be wondering what is all this `ActivatorMiddlewareResolver` class being passed to every instance of pipeline and chain of responsibility. @@ -325,7 +320,7 @@ public class RoudCornersAsyncMiddleware : IAsyncMiddleware } ``` -Or instantiate pipeline/chain of responsibility directly: +Or instantiate it directly: ```C# services.AddMiddlewareFromAssembly(typeof(RoudCornersAsyncMiddleware).Assembly); @@ -379,9 +374,9 @@ With: var exceptionHandlersChain = new ResponsibilityChain(new ActivatorMiddlewareResolver()) .Chain() .Chain() - .Finally(); + .Finally(); -public class FinallyDoSomething : IFinally +public class DoSomething : IFinally { public bool Finally(Exception parameter) { From b0a8d279d304162f4ef869763225a7cdf1fe61ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 23:11:39 +0200 Subject: [PATCH 07/12] extract locals --- src/PipelineNet/AsyncBaseMiddlewareFlow.cs | 3 ++- src/PipelineNet/Pipelines/AsyncPipeline.cs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs index 1db9a3e..88f441d 100644 --- a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs +++ b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs @@ -83,7 +83,8 @@ internal static async Task DisposeMiddlewareAsync(MiddlewareResolverResult middl await asyncDisposable.DisposeAsync().ConfigureAwait(false); } #else - await Task.FromResult(default(int)).ConfigureAwait(false); + var completedTask = Task.FromResult(0); + await completedTask.ConfigureAwait(false); #endif if (middleware is IDisposable disposable) { diff --git a/src/PipelineNet/Pipelines/AsyncPipeline.cs b/src/PipelineNet/Pipelines/AsyncPipeline.cs index 2e72c49..c1f9d12 100644 --- a/src/PipelineNet/Pipelines/AsyncPipeline.cs +++ b/src/PipelineNet/Pipelines/AsyncPipeline.cs @@ -87,7 +87,10 @@ public async Task Execute(TParameter parameter, CancellationToken cancellationTo index++; if (index == MiddlewareTypes.Count) - next = async (p) => await Task.FromResult(default(int)).ConfigureAwait(false); + { + var completedTask = Task.FromResult(0); + next = async (p) => await completedTask.ConfigureAwait(false); + } EnsureMiddlewareNotNull(middlewareResolverResult, middlewareType); await RunMiddlewareAsync(middlewareResolverResult, parameter2, next, cancellationToken).ConfigureAwait(false); From a971e62040337cab83e714b654a92489087e5ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 23:12:00 +0200 Subject: [PATCH 08/12] fix bug in async middleware disposal --- src/PipelineNet/AsyncBaseMiddlewareFlow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs index 88f441d..e474586 100644 --- a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs +++ b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs @@ -82,6 +82,7 @@ internal static async Task DisposeMiddlewareAsync(MiddlewareResolverResult middl { await asyncDisposable.DisposeAsync().ConfigureAwait(false); } + else #else var completedTask = Task.FromResult(0); await completedTask.ConfigureAwait(false); From 30d9e42d5e48863d16651e91a6687548107d1a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 26 Oct 2024 23:30:01 +0200 Subject: [PATCH 09/12] fix test name --- .../ServiceCollectionExtensionsTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PipelineNet.ServiceProvider.Tests/ServiceCollectionExtensionsTests.cs b/src/PipelineNet.ServiceProvider.Tests/ServiceCollectionExtensionsTests.cs index fe3fba5..2e473f4 100644 --- a/src/PipelineNet.ServiceProvider.Tests/ServiceCollectionExtensionsTests.cs +++ b/src/PipelineNet.ServiceProvider.Tests/ServiceCollectionExtensionsTests.cs @@ -38,7 +38,6 @@ public MyService(IAsyncPipeline pipeline) public async Task DoSomething() { Bitmap image = (Bitmap) Image.FromFile("party-photo.png"); - await _pipeline.Execute(image); } } @@ -149,7 +148,7 @@ public ServiceCollectionExtensionsTests(ITestOutputHelper output) } [Fact] - public async Task AddPipelineNet_Works_Readme() + public async Task AddMiddlewareFromAssembly_Works() { var serviceProvider = new ServiceCollection() .AddMiddlewareFromAssembly(typeof(RoudCornersAsyncMiddleware).Assembly) From 68b3f9f9cc5a9659b166ddc10c2ab95e1ddc49ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= <62397363+mariusz96@users.noreply.github.com> Date: Wed, 30 Oct 2024 08:35:22 +0100 Subject: [PATCH 10/12] simplify preprocessor directives in async middleware disposal --- src/PipelineNet/AsyncBaseMiddlewareFlow.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs index e474586..518bea7 100644 --- a/src/PipelineNet/AsyncBaseMiddlewareFlow.cs +++ b/src/PipelineNet/AsyncBaseMiddlewareFlow.cs @@ -83,14 +83,14 @@ internal static async Task DisposeMiddlewareAsync(MiddlewareResolverResult middl await asyncDisposable.DisposeAsync().ConfigureAwait(false); } else -#else - var completedTask = Task.FromResult(0); - await completedTask.ConfigureAwait(false); #endif if (middleware is IDisposable disposable) { disposable.Dispose(); } + + var completedTask = Task.FromResult(0); + await completedTask.ConfigureAwait(false); } } } From ab642aac4a1e66fe53261cdb242d2af58963023e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= <62397363+mariusz96@users.noreply.github.com> Date: Wed, 30 Oct 2024 08:37:15 +0100 Subject: [PATCH 11/12] update readme --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2e1d4bd..2d01fcb 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,9 @@ You can even define a fallback that will be executed after your entire chain: var exceptionHandlersChain = new ResponsibilityChain(new ActivatorMiddlewareResolver()) .Chain() // The order of middleware being chained matters .Chain() - .Finally(); + .Finally(); -public class DoSomething : IFinally +public class ExceptionHandlerFallback : IFinally { public bool Finally(Exception parameter) { @@ -202,9 +202,9 @@ If you want to, you can use the asynchronous version, using asynchronous middlew var exceptionHandlersChain = new AsyncResponsibilityChain(new ActivatorMiddlewareResolver()) .Chain() // The order of middleware being chained matters .Chain() - .Finally(); + .Finally(); -public class ExceptionHandlerFallback : IAsyncFinally +public class ExceptionHandlerAsyncFallback : IAsyncFinally { public Task Finally(Exception parameter) { @@ -374,9 +374,9 @@ With: var exceptionHandlersChain = new ResponsibilityChain(new ActivatorMiddlewareResolver()) .Chain() .Chain() - .Finally(); + .Finally(); -public class DoSomething : IFinally +public class ExceptionHandlerFallback : IFinally { public bool Finally(Exception parameter) { From bd65f54f976c149ae9d9a7d66ff6b2ff3bad3f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20St=C4=99pie=C5=84?= Date: Sat, 2 Nov 2024 17:06:39 +0100 Subject: [PATCH 12/12] add IsDisposable as obsolete property --- .../MiddlewareResolverResult.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs b/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs index b7c5a3b..51f6032 100644 --- a/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs +++ b/src/PipelineNet/MiddlewareResolver/MiddlewareResolverResult.cs @@ -1,4 +1,6 @@ -namespace PipelineNet.MiddlewareResolver +using System; + +namespace PipelineNet.MiddlewareResolver { /// /// Contains the result of . @@ -10,6 +12,19 @@ public class MiddlewareResolverResult /// public object Middleware { get; set; } + /// + /// Gets or sets the value indicating whether the middleware should be disposed. + /// Set this to if the middleware is IDisposable or + /// IAsyncDisposable (requires .NET Standard 2.1 or greater) + /// and is not disposed by a dependency injection container. + /// + [Obsolete("This property is obsolete. Use Dispose.")] + public bool IsDisposable + { + get => Dispose; + set => Dispose = value; + } + /// /// Gets or sets the value indicating whether the middleware should be disposed. /// Set this to if the middleware is not disposed