mirror of
https://github.com/ditkrg/DIT.Workflower.git
synced 2026-01-22 22:06:42 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b653f10e3e | ||
| 4fd1e47787 | |||
| 6de3d47516 | |||
|
|
f6f93d4744 | ||
|
|
b9c79a4781 | ||
| 57c0470179 | |||
| ed95ceea93 | |||
| f76ffcbfa2 | |||
| b614784805 | |||
| 011a2ab9aa | |||
| 599ffc3dc9 | |||
| 8ec528f2e0 | |||
| f99bd9b15c | |||
| bb52ee16d5 | |||
|
|
189d43cc8f | ||
| 28d4f4805f | |||
|
|
812ae4b672 | ||
| 594eaffa87 | |||
| 98f2c02ffe | |||
|
|
b3ac788b8f | ||
|
|
57f2188f7f | ||
| 8c3f6b5f55 | |||
|
|
199f8ce1b5 | ||
| 4379fb6bca | |||
|
|
a6ea2b6d8d | ||
| 36e4e94a44 | |||
|
|
3c45c128fa |
@ -3,16 +3,16 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"dotnet-sonarscanner": {
|
"dotnet-sonarscanner": {
|
||||||
"version": "5.7.2",
|
"version": "6.2.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-sonarscanner"
|
"dotnet-sonarscanner"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dotnet-coverage": {
|
"dotnet-coverage": {
|
||||||
"version": "17.3.2",
|
"version": "17.11.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-coverage"
|
"dotnet-coverage"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@ -4,7 +4,6 @@ updates:
|
|||||||
# Maintain dependencies for GitHub Actions
|
# Maintain dependencies for GitHub Actions
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
target-branch: dev
|
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
reviewers:
|
reviewers:
|
||||||
@ -13,8 +12,7 @@ updates:
|
|||||||
# Maintain dependencies for nuget
|
# Maintain dependencies for nuget
|
||||||
- package-ecosystem: "nuget"
|
- package-ecosystem: "nuget"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
target-branch: dev
|
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
reviewers:
|
reviewers:
|
||||||
- "ditkrg/digital-development-net"
|
- "ditkrg/dotnet"
|
||||||
|
|||||||
9
.github/workflows/deploy-nuget.yaml
vendored
9
.github/workflows/deploy-nuget.yaml
vendored
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
name: Deploy To Nuget
|
name: Deploy To Nuget
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@ -19,13 +20,13 @@ jobs:
|
|||||||
build-push:
|
build-push:
|
||||||
name: Build and Publish
|
name: Build and Publish
|
||||||
needs: [test]
|
needs: [test]
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: "6.0.x"
|
dotnet-version: "8.0.x"
|
||||||
|
|
||||||
- name: Restore packages
|
- name: Restore packages
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
|||||||
42
.github/workflows/sonarqube.yaml
vendored
42
.github/workflows/sonarqube.yaml
vendored
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
name: Run SonarQube Analysis
|
name: Run SonarQube Analysis
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@ -13,39 +14,10 @@ concurrency:
|
|||||||
group: sonarqube-analysis
|
group: sonarqube-analysis
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-tests:
|
test:
|
||||||
name: Run SonarQube Analysis
|
uses: ./.github/workflows/tests-base.yaml
|
||||||
timeout-minutes: 10
|
with:
|
||||||
runs-on: ubuntu-latest
|
sonarqube: true
|
||||||
|
sonarqube_host: ${{ vars.SONARQUBE_HOST }}
|
||||||
env:
|
secrets:
|
||||||
PROJECT_KEY: ditkrg_DIT.Workflower_AYF14rjSb80e2b0bns3t
|
|
||||||
SONARQUBE_HOST: ${{ secrets.SONARQUBE_HOST }}
|
|
||||||
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||||
ASPNETCORE_ENVIRONMENT: Testing
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
|
||||||
|
|
||||||
- name: Set up JDK 11
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: "zulu"
|
|
||||||
java-version: "11"
|
|
||||||
|
|
||||||
- name: Restore tools
|
|
||||||
run: dotnet tool restore
|
|
||||||
|
|
||||||
- name: Run Tests (SonarQube)
|
|
||||||
run: |
|
|
||||||
dotnet tool run dotnet-sonarscanner begin -k:"$PROJECT_KEY" \
|
|
||||||
-d:sonar.login="$SONARQUBE_TOKEN" \
|
|
||||||
-d:sonar.host.url="$SONARQUBE_HOST" \
|
|
||||||
-d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml
|
|
||||||
|
|
||||||
dotnet build --no-incremental
|
|
||||||
dotnet dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
|
|
||||||
|
|
||||||
dotnet tool run dotnet-sonarscanner end -d:sonar.login="$SONARQUBE_TOKEN"
|
|
||||||
|
|||||||
59
.github/workflows/tests-base.yaml
vendored
59
.github/workflows/tests-base.yaml
vendored
@ -12,6 +12,19 @@ on:
|
|||||||
- "!.github/workflows/tests-base.yaml"
|
- "!.github/workflows/tests-base.yaml"
|
||||||
|
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
sonarqube:
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
|
sonarqube_host:
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
SONARQUBE_TOKEN:
|
||||||
|
required: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-tests:
|
run-tests:
|
||||||
@ -23,11 +36,49 @@ jobs:
|
|||||||
ASPNETCORE_ENVIRONMENT: Testing
|
ASPNETCORE_ENVIRONMENT: Testing
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/setup-dotnet@v4
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v2
|
|
||||||
with:
|
with:
|
||||||
dotnet-version: "6.0.x"
|
dotnet-version: "8.0.x"
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
if: ${{ !inputs.sonarqube }}
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
if: ${{ !inputs.sonarqube }}
|
||||||
run: dotnet test
|
run: dotnet test
|
||||||
|
|
||||||
|
###############################
|
||||||
|
########## SONARQUBE ##########
|
||||||
|
###############################
|
||||||
|
- name: Set up JDK
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
if: ${{ inputs.sonarqube }}
|
||||||
|
with:
|
||||||
|
distribution: "zulu"
|
||||||
|
java-version: "17"
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
if: ${{ inputs.sonarqube }}
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
|
|
||||||
|
- name: Restore tools
|
||||||
|
if: ${{ inputs.sonarqube }}
|
||||||
|
run: dotnet tool restore
|
||||||
|
|
||||||
|
- name: Run tests (SonarQube)
|
||||||
|
if: ${{ inputs.sonarqube }}
|
||||||
|
env:
|
||||||
|
PROJECT_KEY: ditkrg_DIT.Workflower_AYF14rjSb80e2b0bns3t
|
||||||
|
SONARQUBE_HOST: ${{ inputs.sonarqube_host }}
|
||||||
|
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
dotnet tool run dotnet-sonarscanner begin -k:"$PROJECT_KEY" \
|
||||||
|
-d:sonar.login="$SONARQUBE_TOKEN" \
|
||||||
|
-d:sonar.host.url="$SONARQUBE_HOST" \
|
||||||
|
-d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml
|
||||||
|
|
||||||
|
dotnet build --no-incremental
|
||||||
|
dotnet dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
|
||||||
|
|
||||||
|
dotnet tool run dotnet-sonarscanner end -d:sonar.login="$SONARQUBE_TOKEN"
|
||||||
|
|||||||
14
README.md
14
README.md
@ -8,15 +8,15 @@ Workflower is a library based on .NET Standard, To handle Finite State Machines
|
|||||||
|
|
||||||
Install the latest nuget package into your ASP.NET Core application.
|
Install the latest nuget package into your ASP.NET Core application.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dotnet add package DIT.Workflower
|
dotnet add package DIT.Workflower
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also download support for Dependency Injection:
|
You can also download support for Dependency Injection:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dotnet add package DIT.Workflower.DependencyInjection
|
dotnet add package DIT.Workflower.DependencyInjection
|
||||||
```
|
```
|
||||||
|
|
||||||
### Workflow Builder
|
### Workflow Builder
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,15 @@ public interface IWorkflow<TState, TCommand, TContext>
|
|||||||
|
|
||||||
string Reference => $"{Id}.v{Version}";
|
string Reference => $"{Id}.v{Version}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves all transition definitions for the workflow.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TState">The type of the workflow state.</typeparam>
|
||||||
|
/// <typeparam name="TCommand">The type of the workflow command.</typeparam>
|
||||||
|
/// <typeparam name="TContext">The type of the workflow context.</typeparam>
|
||||||
|
/// <returns>A list of transition definitions.</returns>
|
||||||
|
public List<TransitionDefinition<TState, TCommand, ContextWrapper<TContext>>> GetAllTransitionDefinitions();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of allowed transitions without any condition checks.
|
/// Gets a list of allowed transitions without any condition checks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -24,4 +33,13 @@ public interface IWorkflow<TState, TCommand, TContext>
|
|||||||
/// <param name="from">The incoming state</param>
|
/// <param name="from">The incoming state</param>
|
||||||
/// <returns>A list of available transitions for the current context</returns>
|
/// <returns>A list of available transitions for the current context</returns>
|
||||||
public List<Transition<TState, TCommand>> GetAllowedTransitions(TContext context, TState from);
|
public List<Transition<TState, TCommand>> GetAllowedTransitions(TContext context, TState from);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a list of allowed transitions based on the provided request.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TState">The type of the workflow state.</typeparam>
|
||||||
|
/// <typeparam name="TCommand">The type of the workflow command.</typeparam>
|
||||||
|
/// <param name="request">The request object containing the necessary information.</param>
|
||||||
|
/// <returns>An enumerable of allowed transitions.</returns>
|
||||||
|
public IEnumerable<Transition<TState, TCommand>> GetAllowedTransitions(ListTransitionsRequest<TState, TCommand, TContext> request);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
namespace DIT.Workflower.DependencyInjection;
|
namespace DIT.Workflower.DependencyInjection;
|
||||||
|
|
||||||
public record DIContextWrapper<TContext>(TContext Context, IServiceProvider ServiceProvider);
|
public record ContextWrapper<TContext>(TContext Context, IServiceProvider ServiceProvider);
|
||||||
|
|||||||
@ -1,13 +1,29 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
<PackageId>DIT.Workflower.DependencyInjection</PackageId>
|
||||||
|
<Authors>DIT</Authors>
|
||||||
|
<Company>DIT</Company>
|
||||||
|
|
||||||
|
<!-- Symbols for nuget -->
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
|
||||||
|
<!-- Deterministic Builds -->
|
||||||
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
|
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup >
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" Condition="'$(TargetFramework)' == 'net6.0'" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" Condition="'$(TargetFramework)' == 'net7.0'" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" Condition="'$(TargetFramework)' == 'net8.0'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
namespace DIT.Workflower.DependencyInjection.Extensions;
|
namespace DIT.Workflower.DependencyInjection.Extensions;
|
||||||
|
|
||||||
public static class IServiceCollectionExtensions
|
public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
|
public static ITransitionStart<TState, TCommand, ContextWrapper<TContext>> AddWorkflowDefinition<TState, TCommand, TContext>(
|
||||||
public static ITransitionStart<TState, TCommand, DIContextWrapper<TContext>> AddWorkflowDefinition<TState, TCommand, TContext>(this IServiceCollection services, in int version = 1)
|
this IServiceCollection services, in int version = 1)
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
@ -13,25 +13,27 @@ public static class IServiceCollectionExtensions
|
|||||||
return AddWorkflowDefinition<TState, TCommand, TContext>(services, id, version);
|
return AddWorkflowDefinition<TState, TCommand, TContext>(services, id, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ITransitionStart<TState, TCommand, DIContextWrapper<TContext>> AddWorkflowDefinition<TState, TCommand, TContext>(this IServiceCollection services, in string id)
|
public static ITransitionStart<TState, TCommand, ContextWrapper<TContext>> AddWorkflowDefinition<TState, TCommand, TContext>(
|
||||||
|
this IServiceCollection services, in string id)
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
return AddWorkflowDefinition<TState, TCommand, TContext>(services, id, version: 1);
|
return AddWorkflowDefinition<TState, TCommand, TContext>(services, id, version: 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ITransitionStart<TState, TCommand, DIContextWrapper<TContext>> AddWorkflowDefinition<TState, TCommand, TContext>(this IServiceCollection services, string id, int version)
|
public static ITransitionStart<TState, TCommand, ContextWrapper<TContext>> AddWorkflowDefinition<TState, TCommand, TContext>(
|
||||||
|
this IServiceCollection services, string id, int version)
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
var builder = WorkflowDefinitionBuilder<TState, TCommand, DIContextWrapper<TContext>>.Create();
|
var builder = WorkflowDefinitionBuilder<TState, TCommand, ContextWrapper<TContext>>.Create();
|
||||||
|
var definition = (WorkflowDefinitionBuilder<TState, TCommand, ContextWrapper<TContext>>)builder;
|
||||||
|
|
||||||
services.TryAddSingleton<IWorkflowFactory<TState, TCommand, DIContextWrapper<TContext>>, DefaultWorkflowFactory<TState, TCommand, DIContextWrapper<TContext>>>();
|
services.TryAddScoped<IWorkflowFactory<TState, TCommand, TContext>, DefaultWorkflowFactory<TState, TCommand, TContext>>();
|
||||||
|
|
||||||
services.AddSingleton<IWorkflow<TState, TCommand, DIContextWrapper<TContext>>, WorkflowDefinitionWrapper<TState, TCommand, DIContextWrapper<TContext>>>(sp =>
|
services.AddScoped<IWorkflow<TState, TCommand, TContext>, WorkflowDefinitionWrapper<TState, TCommand, TContext>>(sp =>
|
||||||
{
|
{
|
||||||
var definition = (WorkflowDefinitionBuilder<TState, TCommand, DIContextWrapper<TContext>>)builder;
|
var wrapper = new WorkflowDefinitionWrapper<TState, TCommand, TContext>(definition, sp, id, version);
|
||||||
var wrapper = new WorkflowDefinitionWrapper<TState, TCommand, DIContextWrapper<TContext>>(definition, id, version);
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
namespace DIT.Workflower.DependencyInjection.Extensions;
|
namespace DIT.Workflower.DependencyInjection.Extensions;
|
||||||
|
|
||||||
public static class IServiceProviderExtensions
|
public static class ServiceProviderExtensions
|
||||||
{
|
{
|
||||||
public static IWorkflowFactory<TState, TCommand, DIContextWrapper<TContext>> GetRequiredWorkflowFactory<TState, TCommand, TContext>(this IServiceProvider sp)
|
public static IWorkflowFactory<TState, TCommand, TContext> GetRequiredWorkflowFactory<TState, TCommand, TContext>(this IServiceProvider sp)
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
return sp.GetRequiredService<IWorkflowFactory<TState, TCommand, DIContextWrapper<TContext>>>();
|
return sp.GetRequiredService<IWorkflowFactory<TState, TCommand, TContext>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IWorkflowFactory<TState, TCommand, DIContextWrapper<TContext>>? GetWorkflowFactory<TState, TCommand, TContext>(this IServiceProvider sp)
|
public static IWorkflowFactory<TState, TCommand, TContext>? GetWorkflowFactory<TState, TCommand, TContext>(this IServiceProvider sp)
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
return sp.GetService<IWorkflowFactory<TState, TCommand, DIContextWrapper<TContext>>>();
|
return sp.GetService<IWorkflowFactory<TState, TCommand, TContext>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IWorkflow<TState, TCommand, DIContextWrapper<TContext>> CreateWorkflow<TState, TCommand, TContext>(this IServiceProvider sp, int version = 1)
|
public static IWorkflow<TState, TCommand, TContext> CreateWorkflow<TState, TCommand, TContext>(this IServiceProvider sp, int version = 1)
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
@ -24,7 +24,7 @@ public static class IServiceProviderExtensions
|
|||||||
return factory.CreateWorkflow(version);
|
return factory.CreateWorkflow(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IWorkflow<TState, TCommand, DIContextWrapper<TContext>> CreateWorkflow<TState, TCommand, TContext>(this IServiceProvider sp, string id, int version = 1)
|
public static IWorkflow<TState, TCommand, TContext> CreateWorkflow<TState, TCommand, TContext>(this IServiceProvider sp, string id, int version = 1)
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,21 +1,56 @@
|
|||||||
namespace DIT.Workflower.DependencyInjection;
|
namespace DIT.Workflower.DependencyInjection;
|
||||||
|
|
||||||
public record WorkflowDefinitionWrapper<TState, TCommand, TContext> : WorkflowDefinition<TState, TCommand, TContext>, IWorkflow<TState, TCommand, TContext>
|
public sealed class WorkflowDefinitionWrapper<TState, TCommand, TContext> : IWorkflow<TState, TCommand, TContext>
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly WorkflowDefinition<TState, TCommand, ContextWrapper<TContext>> _definition;
|
||||||
|
|
||||||
public string Id { get; }
|
public string Id { get; }
|
||||||
|
|
||||||
public int Version { get; }
|
public int Version { get; }
|
||||||
|
public List<TransitionDefinition<TState, TCommand, ContextWrapper<TContext>>> GetAllTransitionDefinitions()
|
||||||
public WorkflowDefinitionWrapper(WorkflowDefinitionBuilder<TState, TCommand, TContext> builder, string id, int version)
|
|
||||||
: base(builder.Transitions)
|
|
||||||
{
|
{
|
||||||
|
return _definition.GetAllTransitionDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Transition<TState, TCommand>> GetAllowedTransitions(TState from)
|
||||||
|
{
|
||||||
|
return _definition.GetAllowedTransitions(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Transition<TState, TCommand>> GetAllowedTransitions(TContext context, TState from)
|
||||||
|
{
|
||||||
|
return _definition.GetAllowedTransitions(GetContextWrapper(context), from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Transition<TState, TCommand>> GetAllowedTransitions(ListTransitionsRequest<TState, TCommand, TContext> request)
|
||||||
|
{
|
||||||
|
var wrappedRequest = new ListTransitionsRequest<TState, TCommand, ContextWrapper<TContext>>
|
||||||
|
{
|
||||||
|
From = request.From,
|
||||||
|
To = request.To,
|
||||||
|
Command = request.Command,
|
||||||
|
Context = request.Context is null ? null : GetContextWrapper(request.Context)
|
||||||
|
};
|
||||||
|
|
||||||
|
return _definition.GetAllowedTransitions(wrappedRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkflowDefinitionWrapper(WorkflowDefinitionBuilder<TState, TCommand, ContextWrapper<TContext>> builder, IServiceProvider serviceProvider, string id, int version)
|
||||||
|
{
|
||||||
|
_definition = builder.Build();
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
|
||||||
Id = id;
|
Id = id;
|
||||||
Version = version;
|
Version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ContextWrapper<TContext> GetContextWrapper(in TContext context)
|
||||||
|
=> new(context, _serviceProvider);
|
||||||
|
|
||||||
public static string GetDefaultId()
|
public static string GetDefaultId()
|
||||||
{
|
{
|
||||||
var ctxType = typeof(TContext);
|
var ctxType = typeof(TContext);
|
||||||
|
|||||||
@ -5,6 +5,20 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
<PackageId>DIT.Workflower</PackageId>
|
||||||
|
<Authors>DIT</Authors>
|
||||||
|
<Company>DIT</Company>
|
||||||
|
|
||||||
|
<!-- Symbols for nuget -->
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
|
||||||
|
<!-- Deterministic Builds -->
|
||||||
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
|
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
15
src/DIT.Workflower/Query.cs
Normal file
15
src/DIT.Workflower/Query.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace DIT.Workflower;
|
||||||
|
|
||||||
|
|
||||||
|
public sealed class ListTransitionsRequest<TState, TCommand, TContext>
|
||||||
|
where TState : struct
|
||||||
|
where TCommand : struct
|
||||||
|
{
|
||||||
|
public TState? From { get; set; }
|
||||||
|
|
||||||
|
public TState? To { get; set; }
|
||||||
|
|
||||||
|
public TCommand? Command { get; set; }
|
||||||
|
|
||||||
|
public TContext? Context { get; set; }
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
namespace DIT.Workflower;
|
namespace DIT.Workflower;
|
||||||
|
|
||||||
public record WorkflowDefinition<TState, TCommand, TContext>
|
public class WorkflowDefinition<TState, TCommand, TContext>
|
||||||
where TState : struct
|
where TState : struct
|
||||||
where TCommand : struct
|
where TCommand : struct
|
||||||
{
|
{
|
||||||
@ -12,6 +12,8 @@ public record WorkflowDefinition<TState, TCommand, TContext>
|
|||||||
_transitions = transitions;
|
_transitions = transitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TransitionDefinition<TState, TCommand, TContext>> GetAllTransitionDefinitions() => _transitions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lists all allowed transitions from current state for the given context.
|
/// Lists all allowed transitions from current state for the given context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,4 +35,33 @@ public record WorkflowDefinition<TState, TCommand, TContext>
|
|||||||
|
|
||||||
return query.Select(x => x.ToTransition()).ToList();
|
return query.Select(x => x.ToTransition()).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<Transition<TState, TCommand>> GetAllowedTransitions(ListTransitionsRequest<TState, TCommand, TContext> request)
|
||||||
|
{
|
||||||
|
var query = _transitions.AsQueryable();
|
||||||
|
|
||||||
|
if (request.From is { } from)
|
||||||
|
{
|
||||||
|
query = query.Where(doc => doc.From.Equals(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.To is { } to)
|
||||||
|
{
|
||||||
|
query = query.Where(doc => doc.To.Equals(to));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Command is { } command)
|
||||||
|
{
|
||||||
|
query = query.Where(doc => doc.Command.Equals(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Context is not null)
|
||||||
|
{
|
||||||
|
query = query.Where(doc => doc.Conditions == null || doc.Conditions.All(cond => cond(request.Context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Select(x => x.ToTransition());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,14 +9,14 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
<PackageReference Include="coverlet.collector" Version="3.2.0">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using DIT.Workflower.DependencyInjection.Abstractions;
|
using DIT.Workflower.DependencyInjection.Extensions;
|
||||||
using DIT.Workflower.DependencyInjection.Extensions;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace DIT.Workflower.Tests.DependencyInjection;
|
namespace DIT.Workflower.Tests.DependencyInjection;
|
||||||
@ -49,7 +48,6 @@ public class DependencyInjectionTests
|
|||||||
Assert.NotNull(v1);
|
Assert.NotNull(v1);
|
||||||
Assert.NotNull(v2);
|
Assert.NotNull(v2);
|
||||||
|
|
||||||
|
|
||||||
Assert.Single(v1!.GetAllowedTransitions(PhoneState.Idle));
|
Assert.Single(v1!.GetAllowedTransitions(PhoneState.Idle));
|
||||||
Assert.Single(v2!.GetAllowedTransitions(PhoneState.Idle));
|
Assert.Single(v2!.GetAllowedTransitions(PhoneState.Idle));
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user