PipelineNet
PipelineNet copied to clipboard
Obsolete Finally
The Finally methods with Func parameters:
public interface IAsyncResponsibilityChain<TParameter, TReturn>
{
IAsyncResponsibilityChain<TParameter, TReturn> Finally(Func<TParameter, Task<TReturn>> finallyFunc);
}
public interface IResponsibilityChain<TParameter, TReturn>
{
IResponsibilityChain<TParameter, TReturn> Finally(Func<TParameter, TReturn> finallyFunc);
}
do not support DI. Also they might lead less knowledgeable developers to unintentionally capture DI services as variables in the function body:
.Finally(async (ctx) =>
{
_dbContext.Logs.Add(new Log { Message = "Failed to process request with id: {ctx.Id}." }); // DbContext captured outside of DI.
await _dbContext.SaveChangesAsync();
})
So I propose to refactor them into classes:
+ public interface ICancellableAsyncFinally<TParameter, TReturn>
+ {
+ Task<TReturn> Finally(TParameter parameter, CancellationToken cancellationToken);
+ }
+ public interface IAsyncFinally<TParameter, TReturn>
+ {
+ Task<TReturn> Finally(TParameter parameter);
+ }
public interface IAsyncResponsibilityChain<TParameter, TReturn>
{
+ IAsyncResponsibilityChain<TParameter, TReturn> Finally<TFinally>() where TFinally : IAsyncFinally<TParameter, TReturn>;
+ IAsyncResponsibilityChain<TParameter, TReturn> CancellableFinally<TCancellableFinally>() where TCancellableFinally : ICancellableAsyncFinally<TParameter, TReturn>;
+ IAsyncResponsibilityChain<TParameter, TReturn> Finally(Type finallyType);
}
+ public interface IFinally<TParameter, TReturn>
+ {
+ TReturn Finally(TParameter parameter);
+ }
public interface IResponsibilityChain<TParameter, TReturn>
{
+ IResponsibilityChain<TParameter, TReturn> Finally<TFinally>() where TFinally : IFinally<TParameter, TReturn>;
+ IResponsibilityChain<TParameter, TReturn> Finally(Type finallyType);
}
And obsolete overloads that use Func.
This would ensure that the old code still compiles while the new code can use DI and avoid "captured services" pitfall.