Добавьте файлы проекта.
This commit is contained in:
6
src/PipelineFramework.Abstractions/IPipeline.cs
Normal file
6
src/PipelineFramework.Abstractions/IPipeline.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace PipelineFramework.Abstractions;
|
||||
|
||||
public interface IPipeline<TContext>
|
||||
{
|
||||
Task ExecuteAsync(TContext context);
|
||||
}
|
||||
7
src/PipelineFramework.Abstractions/IPipelineHook.cs
Normal file
7
src/PipelineFramework.Abstractions/IPipelineHook.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace PipelineFramework.Abstractions;
|
||||
|
||||
public interface IPipelineHook<TContext>
|
||||
{
|
||||
Task OnBeforeExecuteAsync(TContext context);
|
||||
Task OnAfterExecuteAsync(TContext context);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace PipelineFramework.Abstractions;
|
||||
|
||||
public interface IPipelineMiddleware<TContext>
|
||||
{
|
||||
Task InvokeAsync(TContext context, Func<Task> next);
|
||||
}
|
||||
8
src/PipelineFramework.Abstractions/IPipelineModule.cs
Normal file
8
src/PipelineFramework.Abstractions/IPipelineModule.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace PipelineFramework.Abstractions;
|
||||
|
||||
public interface IPipelineModule<TContext>
|
||||
{
|
||||
string Id { get; }
|
||||
IEnumerable<string> DependsOn { get; }
|
||||
Task ExecuteAsync(TContext context);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
17
src/PipelineFramework.DI/PipelineFramework.DI.csproj
Normal file
17
src/PipelineFramework.DI/PipelineFramework.DI.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PipelineFramework\PipelineFramework.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,20 @@
|
||||
using PipelineFramework;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
public static class PipelineServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddPipeline<TContext>(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<IPipeline<TContext>>(provider =>
|
||||
{
|
||||
var modules = provider.GetServices<IPipelineModule<TContext>>().ToList();
|
||||
var middlewares = provider.GetServices<IPipelineMiddleware<TContext>>().ToList();
|
||||
var hooks = provider.GetServices<IPipelineHook<TContext>>().ToList();
|
||||
|
||||
return new Pipeline<TContext>(modules, middlewares, hooks);
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
6
src/PipelineFramework/Abstractions/IPipeline.cs
Normal file
6
src/PipelineFramework/Abstractions/IPipeline.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace PipelineFramework;
|
||||
|
||||
public interface IPipeline<TContext>
|
||||
{
|
||||
Task RunAsync(TContext context);
|
||||
}
|
||||
8
src/PipelineFramework/Abstractions/IPipelineHook.cs
Normal file
8
src/PipelineFramework/Abstractions/IPipelineHook.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace PipelineFramework;
|
||||
|
||||
public interface IPipelineHook<TContext>
|
||||
{
|
||||
Task OnBeforeAsync(TContext context, IPipelineModule<TContext> module);
|
||||
Task OnAfterAsync(TContext context, IPipelineModule<TContext> module);
|
||||
Task OnErrorAsync(TContext context, IPipelineModule<TContext> module, Exception ex);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace PipelineFramework;
|
||||
|
||||
public interface IPipelineMiddleware<TContext>
|
||||
{
|
||||
Task InvokeAsync(TContext context, Func<Task> next);
|
||||
}
|
||||
9
src/PipelineFramework/Abstractions/IPipelineModule.cs
Normal file
9
src/PipelineFramework/Abstractions/IPipelineModule.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace PipelineFramework;
|
||||
|
||||
public interface IPipelineModule<TContext>
|
||||
{
|
||||
string Id { get; }
|
||||
IEnumerable<string> DependsOn { get; }
|
||||
|
||||
Task ExecuteAsync(TContext context);
|
||||
}
|
||||
70
src/PipelineFramework/Core/Pipeline.cs
Normal file
70
src/PipelineFramework/Core/Pipeline.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
namespace PipelineFramework;
|
||||
|
||||
public class Pipeline<TContext> : IPipeline<TContext>
|
||||
{
|
||||
private readonly List<IPipelineModule<TContext>> _modules;
|
||||
private readonly List<IPipelineMiddleware<TContext>> _middlewares;
|
||||
private readonly List<IPipelineHook<TContext>> _hooks;
|
||||
|
||||
|
||||
public Pipeline(
|
||||
List<IPipelineModule<TContext>> modules,
|
||||
List<IPipelineMiddleware<TContext>> middlewares,
|
||||
List<IPipelineHook<TContext>> hooks)
|
||||
{
|
||||
_modules = modules;
|
||||
_middlewares = middlewares;
|
||||
_hooks = hooks;
|
||||
}
|
||||
|
||||
public async Task RunAsync(TContext context)
|
||||
{
|
||||
var executed = new HashSet<string>();
|
||||
var moduleMap = _modules.ToDictionary(m => m.Id);
|
||||
|
||||
Func<Task> pipeline = async () =>
|
||||
{
|
||||
while (executed.Count < _modules.Count)
|
||||
{
|
||||
var ready = _modules
|
||||
.Where(m => !executed.Contains(m.Id) &&
|
||||
m.DependsOn.All(dep => executed.Contains(dep)))
|
||||
.ToList();
|
||||
|
||||
var tasks = ready.Select(m => ExecuteModuleWithHooksAsync(m, context)).ToList();
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
foreach (var m in ready)
|
||||
executed.Add(m.Id);
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var middleware in _middlewares.Reverse())
|
||||
{
|
||||
var next = pipeline;
|
||||
pipeline = () => middleware(context, next);
|
||||
}
|
||||
|
||||
await pipeline();
|
||||
}
|
||||
|
||||
private async Task ExecuteModuleWithHooksAsync(IPipelineModule<TContext> module, TContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var hook in _hooks)
|
||||
await hook.OnBeforeAsync(context, module);
|
||||
|
||||
await module.ExecuteAsync(context);
|
||||
|
||||
foreach (var hook in _hooks)
|
||||
await hook.OnAfterAsync(context, module);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (var hook in _hooks)
|
||||
await hook.OnErrorAsync(context, module, ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/PipelineFramework/Core/PipelineBuilder.cs
Normal file
38
src/PipelineFramework/Core/PipelineBuilder.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace PipelineFramework;
|
||||
|
||||
public abstract class PipelineBuilder<TContext>
|
||||
{
|
||||
private readonly List<IPipelineModule<TContext>> _modules = new();
|
||||
private readonly List<Func<TContext, Func<Task>, Task>> _middlewares = new();
|
||||
private readonly List<IPipelineHook<TContext>> _hooks = new();
|
||||
|
||||
public PipelineBuilder<TContext> AddModule(IPipelineModule<TContext> module)
|
||||
{
|
||||
_modules.Add(module);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PipelineBuilder<TContext> UseMiddleware<T>() where T : IPipelineMiddleware<TContext>, new()
|
||||
{
|
||||
_middlewares.Add((ctx, next) => new T().InvokeAsync(ctx, next));
|
||||
return this;
|
||||
}
|
||||
|
||||
public PipelineBuilder<TContext> UseMiddleware(Func<TContext, Func<Task>, Task> middleware)
|
||||
{
|
||||
_middlewares.Add(middleware);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PipelineBuilder<TContext> AddHook(IPipelineHook<TContext> hook)
|
||||
{
|
||||
_hooks.Add(hook);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected IReadOnlyList<IPipelineModule<TContext>> Modules => _modules;
|
||||
protected IReadOnlyList<Func<TContext, Func<Task>, Task>> Middlewares => _middlewares;
|
||||
protected IReadOnlyList<IPipelineHook<TContext>> Hooks => _hooks;
|
||||
|
||||
public abstract IPipeline<TContext> Build();
|
||||
}
|
||||
9
src/PipelineFramework/PipelineFramework.csproj
Normal file
9
src/PipelineFramework/PipelineFramework.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user