Добавьте файлы проекта.
This commit is contained in:
132
.gitea/workflows/ManualRelease.yaml
Normal file
132
.gitea/workflows/ManualRelease.yaml
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
name: Ручное создание релиза
|
||||||
|
run-name: ${{ gitea.actor }} запустил создание релиза
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version_type:
|
||||||
|
description: 'Тип версии'
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- major
|
||||||
|
- minor
|
||||||
|
- patch
|
||||||
|
default: 'patch'
|
||||||
|
pre_release:
|
||||||
|
description: "Отметка pre-release (для не master веток всегда true)"
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
dotnet: [ '8.0.x' ]
|
||||||
|
|
||||||
|
name: .Net ${{ matrix.dotnet }} Release
|
||||||
|
steps:
|
||||||
|
- name: Получение исходников
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Полная история для тегов
|
||||||
|
|
||||||
|
- name: Автоматическое определение pre-release
|
||||||
|
id: pre-release-detector
|
||||||
|
run: |
|
||||||
|
# Определяем ветку по умолчанию (main/master)
|
||||||
|
DEFAULT_BRANCH=$(git remote show origin | grep 'HEAD branch' | awk '{print $3}')
|
||||||
|
echo "Default branch: $DEFAULT_BRANCH"
|
||||||
|
|
||||||
|
# Если текущая ветка не дефолтная - форсируем pre-release
|
||||||
|
if [ "$GITHUB_REF_NAME" != "$DEFAULT_BRANCH" ]; then
|
||||||
|
echo "Ветка не master - устанавливаем pre-release"
|
||||||
|
echo "PRE_RELEASE=true" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "Ветка master - используем pre-release из параметров"
|
||||||
|
echo "PRE_RELEASE=${{ github.event.inputs.pre_release }}" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Получение последней версии
|
||||||
|
id: versioning
|
||||||
|
run: |
|
||||||
|
# Получаем последний тег
|
||||||
|
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
|
||||||
|
echo "Последний тэг: $LATEST_TAG"
|
||||||
|
|
||||||
|
# Извлекаем цифры версии
|
||||||
|
VERSION="${LATEST_TAG#v}"
|
||||||
|
|
||||||
|
if [[ ! $VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-.+)?$ ]]; then
|
||||||
|
echo "Неверный формат версии: $VERSION"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAJOR=${BASH_REMATCH[1]}
|
||||||
|
MINOR=${BASH_REMATCH[2]}
|
||||||
|
PATCH=${BASH_REMATCH[3]}
|
||||||
|
|
||||||
|
# Увеличиваем версию
|
||||||
|
case "${{ github.event.inputs.version_type }}" in
|
||||||
|
major)
|
||||||
|
MAJOR=$((MAJOR + 1))
|
||||||
|
MINOR=0
|
||||||
|
PATCH=0
|
||||||
|
;;
|
||||||
|
minor)
|
||||||
|
MINOR=$((MINOR + 1))
|
||||||
|
PATCH=0
|
||||||
|
;;
|
||||||
|
patch)
|
||||||
|
PATCH=$((PATCH + 1))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
BASE_VERSION="$MAJOR.$MINOR.$PATCH"
|
||||||
|
|
||||||
|
# Добавим pre-release, если требуется
|
||||||
|
if ${{ env.PRE_RELEASE }}; then
|
||||||
|
TIMESTAMP=$(date -u +"%Y%m%d%H%M%S")
|
||||||
|
NEW_VERSION="$BASE_VERSION-pre.$TIMESTAMP"
|
||||||
|
else
|
||||||
|
NEW_VERSION="$BASE_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Новая версия: $NEW_VERSION"
|
||||||
|
echo "VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "VERSION=$NEW_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Настройка .NET Core
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
dotnet-version: ${{ matrix.dotnet }}
|
||||||
|
|
||||||
|
- name: Установка версии RetailUpdatesBot
|
||||||
|
run: |
|
||||||
|
sed -i "s/<Version>.*<\/Version>/<Version>${{ env.VERSION }}<\/Version>/g" ./RetailUpdatesBot/RetailUpdatesBot.csproj
|
||||||
|
|
||||||
|
- name: Восстановление зависимостей
|
||||||
|
run: dotnet restore --nologo
|
||||||
|
|
||||||
|
- name: Сборка решения
|
||||||
|
run: dotnet build --no-restore --nologo
|
||||||
|
|
||||||
|
- name: Публикация
|
||||||
|
run: dotnet publish RetailUpdatesBot --configuration Release --runtime win-x64 --artifacts-path artifacts --nologo
|
||||||
|
|
||||||
|
- name: Создание ZIP архива
|
||||||
|
run: |
|
||||||
|
cd artifacts/publish/RetailUpdatesBot/release_win-x64/
|
||||||
|
zip -r ../RetailUpdatesBot-v${{ env.VERSION }}.zip *
|
||||||
|
cd ..
|
||||||
|
echo "ZIP_PATH=RetailUpdatesBot-v${{ env.VERSION }}.zip" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Создание релиза
|
||||||
|
uses: https://gitea.com/actions/gitea-release-action@v1
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
|
||||||
|
with:
|
||||||
|
files: artifacts/publish/RetailUpdatesBot/RetailUpdatesBot-v${{ env.VERSION }}.zip
|
||||||
|
tag_name: v${{ env.VERSION }}
|
||||||
|
name: RetailUpdatesBot-v${{ env.VERSION }}
|
||||||
|
body: "## Что нового\n\n- Описание изменений\n- Функциональность\n- Исправления"
|
||||||
|
prerelease: ${{ env.PRE_RELEASE }}
|
||||||
22
Directory.Build.props
Normal file
22
Directory.Build.props
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Общие настройки -->
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<WarningsNotAsErrors>CS1591</WarningsNotAsErrors>
|
||||||
|
|
||||||
|
<!-- Метаданные для NuGet -->
|
||||||
|
<Authors>FrigaT</Authors>
|
||||||
|
<Product>PipelineFramework</Product>
|
||||||
|
<Description>Гибкий и лёгкий фреймворк конвейеров для .NET-приложений</Description>
|
||||||
|
<PackageProjectUrl>https://github.com/MaxLabs/PipelineFramework</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/MaxLabs/PipelineFramework</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageTags>pipeline;framework;middleware;dotnet</PackageTags>
|
||||||
|
<Version>0.0.1</Version>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
43
PipelineFramework.sln
Normal file
43
PipelineFramework.sln
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.36414.22
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PipelineFramework", "src\PipelineFramework\PipelineFramework.csproj", "{4407AD88-6FFC-47CF-B06A-BC1D9E05B7E5}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PipelineFramework.DI", "src\PipelineFramework.DI\PipelineFramework.DI.csproj", "{B5D47E22-BD13-458B-ACDC-2017C962AE80}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Элементы решения", "Элементы решения", "{754FC069-D67B-A9D7-50A1-8D1CA196D8F1}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
Directory.Build.props = Directory.Build.props
|
||||||
|
README.md = README.md
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{4407AD88-6FFC-47CF-B06A-BC1D9E05B7E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4407AD88-6FFC-47CF-B06A-BC1D9E05B7E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4407AD88-6FFC-47CF-B06A-BC1D9E05B7E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4407AD88-6FFC-47CF-B06A-BC1D9E05B7E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B5D47E22-BD13-458B-ACDC-2017C962AE80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B5D47E22-BD13-458B-ACDC-2017C962AE80}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B5D47E22-BD13-458B-ACDC-2017C962AE80}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B5D47E22-BD13-458B-ACDC-2017C962AE80}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{4407AD88-6FFC-47CF-B06A-BC1D9E05B7E5} = {36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}
|
||||||
|
{B5D47E22-BD13-458B-ACDC-2017C962AE80} = {36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {22A2D53A-92B8-4C82-A391-6A00DE84526C}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# PipelineFramework
|
||||||
|
|
||||||
|
**PipelineFramework** — это гибкий и лёгкий фреймворк для построения конвейеров обработки данных и логики в .NET-приложениях.
|
||||||
|
Он позволяет создавать последовательности шагов (middleware), которые обрабатывают входные данные, управляют потоком выполнения и обеспечивают расширяемость.
|
||||||
|
|
||||||
|
## 🚀 Возможности
|
||||||
|
|
||||||
|
- Простое определение шагов конвейера
|
||||||
|
- Поддержка асинхронной обработки
|
||||||
|
- Встроенная DI-интеграция
|
||||||
|
- Расширяемость через интерфейсы
|
||||||
|
- Минимум зависимостей
|
||||||
|
|
||||||
|
## 📦 Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet add package PipelineFramework
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧩 Пример использования
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var pipeline = new PipelineBuilder<string>()
|
||||||
|
.Use(async (input, next) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Step 1: {input}");
|
||||||
|
await next(input + " → Step1");
|
||||||
|
})
|
||||||
|
.Use(async (input, next) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Step 2: {input}");
|
||||||
|
await next(input + " → Step2");
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
await pipeline.ExecuteAsync("Start");
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Документация
|
||||||
|
|
||||||
|
- [Примеры использования](docs/examples.md)
|
||||||
|
- [Интеграция с DI](docs/di.md)
|
||||||
|
- [Расширение фреймворка](docs/extending.md)
|
||||||
|
|
||||||
|
## 🛠 Требования
|
||||||
|
|
||||||
|
- .NET 9.0 или выше
|
||||||
|
|
||||||
|
## 🧑💻 Автор
|
||||||
|
|
||||||
|
Разработано [FrigaT](https://github.com/FrigaT)
|
||||||
|
|
||||||
|
## 📄 Лицензия
|
||||||
|
|
||||||
|
Проект распространяется под лицензией [MIT](LICENSE)
|
||||||
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