From 6de3d475160dfd37fc9ce0d17bdd86a754f33dd8 Mon Sep 17 00:00:00 2001 From: "Shkar T. Noori" Date: Wed, 14 Aug 2024 12:56:39 +0300 Subject: [PATCH] BREAKING: Use Scoped services for the IWorkflow in DI. --- .../Abstractions/IWorkflow.cs | 2 +- .../Common.cs | 2 +- .../DIT.Workflower.DependencyInjection.csproj | 8 ++-- .../IServiceCollectionExtensions.cs | 22 +++++----- .../Extensions/IServiceProviderExtensions.cs | 14 +++--- .../WorkflowDefinitionWrapper.cs | 43 +++++++++++++++++-- src/DIT.Workflower/DIT.Workflower.csproj | 2 +- src/DIT.Workflower/WorkflowDefinition.cs | 10 ++--- .../DependencyInjectionTests.cs | 4 +- 9 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/DIT.Workflower.DependencyInjection/Abstractions/IWorkflow.cs b/src/DIT.Workflower.DependencyInjection/Abstractions/IWorkflow.cs index fec6118..b4dd250 100644 --- a/src/DIT.Workflower.DependencyInjection/Abstractions/IWorkflow.cs +++ b/src/DIT.Workflower.DependencyInjection/Abstractions/IWorkflow.cs @@ -17,7 +17,7 @@ public interface IWorkflow /// The type of the workflow command. /// The type of the workflow context. /// A list of transition definitions. - public List> GetAllTransitionDefinitions(); + public List>> GetAllTransitionDefinitions(); /// /// Gets a list of allowed transitions without any condition checks. diff --git a/src/DIT.Workflower.DependencyInjection/Common.cs b/src/DIT.Workflower.DependencyInjection/Common.cs index d2235ac..c378796 100644 --- a/src/DIT.Workflower.DependencyInjection/Common.cs +++ b/src/DIT.Workflower.DependencyInjection/Common.cs @@ -1,3 +1,3 @@ namespace DIT.Workflower.DependencyInjection; -public record DIContextWrapper(TContext Context, IServiceProvider ServiceProvider); +public record ContextWrapper(TContext Context, IServiceProvider ServiceProvider); diff --git a/src/DIT.Workflower.DependencyInjection/DIT.Workflower.DependencyInjection.csproj b/src/DIT.Workflower.DependencyInjection/DIT.Workflower.DependencyInjection.csproj index d4560d0..7bbc013 100644 --- a/src/DIT.Workflower.DependencyInjection/DIT.Workflower.DependencyInjection.csproj +++ b/src/DIT.Workflower.DependencyInjection/DIT.Workflower.DependencyInjection.csproj @@ -16,14 +16,14 @@ true - true + true - - - + + + diff --git a/src/DIT.Workflower.DependencyInjection/Extensions/IServiceCollectionExtensions.cs b/src/DIT.Workflower.DependencyInjection/Extensions/IServiceCollectionExtensions.cs index 269b7c7..6cb4fc8 100644 --- a/src/DIT.Workflower.DependencyInjection/Extensions/IServiceCollectionExtensions.cs +++ b/src/DIT.Workflower.DependencyInjection/Extensions/IServiceCollectionExtensions.cs @@ -2,10 +2,10 @@ namespace DIT.Workflower.DependencyInjection.Extensions; -public static class IServiceCollectionExtensions +public static class ServiceCollectionExtensions { - - public static ITransitionStart> AddWorkflowDefinition(this IServiceCollection services, in int version = 1) + public static ITransitionStart> AddWorkflowDefinition( + this IServiceCollection services, in int version = 1) where TState : struct where TCommand : struct { @@ -13,25 +13,27 @@ public static class IServiceCollectionExtensions return AddWorkflowDefinition(services, id, version); } - public static ITransitionStart> AddWorkflowDefinition(this IServiceCollection services, in string id) + public static ITransitionStart> AddWorkflowDefinition( + this IServiceCollection services, in string id) where TState : struct where TCommand : struct { return AddWorkflowDefinition(services, id, version: 1); } - public static ITransitionStart> AddWorkflowDefinition(this IServiceCollection services, string id, int version) + public static ITransitionStart> AddWorkflowDefinition( + this IServiceCollection services, string id, int version) where TState : struct where TCommand : struct { - var builder = WorkflowDefinitionBuilder>.Create(); + var builder = WorkflowDefinitionBuilder>.Create(); + var definition = (WorkflowDefinitionBuilder>)builder; - services.TryAddSingleton>, DefaultWorkflowFactory>>(); + services.TryAddScoped, DefaultWorkflowFactory>(); - services.AddSingleton>, WorkflowDefinitionWrapper>>(sp => + services.AddScoped, WorkflowDefinitionWrapper>(sp => { - var definition = (WorkflowDefinitionBuilder>)builder; - var wrapper = new WorkflowDefinitionWrapper>(definition, id, version); + var wrapper = new WorkflowDefinitionWrapper(definition, sp, id, version); return wrapper; }); diff --git a/src/DIT.Workflower.DependencyInjection/Extensions/IServiceProviderExtensions.cs b/src/DIT.Workflower.DependencyInjection/Extensions/IServiceProviderExtensions.cs index a094cf3..f501c9d 100644 --- a/src/DIT.Workflower.DependencyInjection/Extensions/IServiceProviderExtensions.cs +++ b/src/DIT.Workflower.DependencyInjection/Extensions/IServiceProviderExtensions.cs @@ -1,22 +1,22 @@ namespace DIT.Workflower.DependencyInjection.Extensions; -public static class IServiceProviderExtensions +public static class ServiceProviderExtensions { - public static IWorkflowFactory> GetRequiredWorkflowFactory(this IServiceProvider sp) + public static IWorkflowFactory GetRequiredWorkflowFactory(this IServiceProvider sp) where TState : struct where TCommand : struct { - return sp.GetRequiredService>>(); + return sp.GetRequiredService>(); } - public static IWorkflowFactory>? GetWorkflowFactory(this IServiceProvider sp) + public static IWorkflowFactory? GetWorkflowFactory(this IServiceProvider sp) where TState : struct where TCommand : struct { - return sp.GetService>>(); + return sp.GetService>(); } - public static IWorkflow> CreateWorkflow(this IServiceProvider sp, int version = 1) + public static IWorkflow CreateWorkflow(this IServiceProvider sp, int version = 1) where TState : struct where TCommand : struct { @@ -24,7 +24,7 @@ public static class IServiceProviderExtensions return factory.CreateWorkflow(version); } - public static IWorkflow> CreateWorkflow(this IServiceProvider sp, string id, int version = 1) + public static IWorkflow CreateWorkflow(this IServiceProvider sp, string id, int version = 1) where TState : struct where TCommand : struct { diff --git a/src/DIT.Workflower.DependencyInjection/WorkflowDefinitionWrapper.cs b/src/DIT.Workflower.DependencyInjection/WorkflowDefinitionWrapper.cs index 571d512..fc2546e 100644 --- a/src/DIT.Workflower.DependencyInjection/WorkflowDefinitionWrapper.cs +++ b/src/DIT.Workflower.DependencyInjection/WorkflowDefinitionWrapper.cs @@ -1,21 +1,56 @@ namespace DIT.Workflower.DependencyInjection; -public record WorkflowDefinitionWrapper : WorkflowDefinition, IWorkflow +public sealed class WorkflowDefinitionWrapper : IWorkflow where TState : struct where TCommand : struct { + private readonly IServiceProvider _serviceProvider; + private readonly WorkflowDefinition> _definition; + public string Id { get; } public int Version { get; } - - public WorkflowDefinitionWrapper(WorkflowDefinitionBuilder builder, string id, int version) - : base(builder.Transitions) + public List>> GetAllTransitionDefinitions() { + return _definition.GetAllTransitionDefinitions(); + } + + public List> GetAllowedTransitions(TState from) + { + return _definition.GetAllowedTransitions(from); + } + + public List> GetAllowedTransitions(TContext context, TState from) + { + return _definition.GetAllowedTransitions(GetContextWrapper(context), from); + } + + public IEnumerable> GetAllowedTransitions(ListTransitionsRequest request) + { + var wrappedRequest = new ListTransitionsRequest> + { + 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> builder, IServiceProvider serviceProvider, string id, int version) + { + _definition = builder.Build(); + _serviceProvider = serviceProvider; + Id = id; Version = version; } + private ContextWrapper GetContextWrapper(in TContext context) + => new(context, _serviceProvider); + public static string GetDefaultId() { var ctxType = typeof(TContext); diff --git a/src/DIT.Workflower/DIT.Workflower.csproj b/src/DIT.Workflower/DIT.Workflower.csproj index 57417a8..f35b326 100644 --- a/src/DIT.Workflower/DIT.Workflower.csproj +++ b/src/DIT.Workflower/DIT.Workflower.csproj @@ -17,7 +17,7 @@ true - true + true diff --git a/src/DIT.Workflower/WorkflowDefinition.cs b/src/DIT.Workflower/WorkflowDefinition.cs index 45ce199..9459e71 100644 --- a/src/DIT.Workflower/WorkflowDefinition.cs +++ b/src/DIT.Workflower/WorkflowDefinition.cs @@ -1,6 +1,6 @@ namespace DIT.Workflower; -public record WorkflowDefinition +public class WorkflowDefinition where TState : struct where TCommand : struct { @@ -41,24 +41,24 @@ public record WorkflowDefinition { var query = _transitions.AsQueryable(); - if (request.From is TState from) + if (request.From is { } from) { query = query.Where(doc => doc.From.Equals(from)); } - if (request.To is TState to) + if (request.To is { } to) { query = query.Where(doc => doc.To.Equals(to)); } - if (request.Command is TCommand command) + 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.Any(cond => !cond(request.Context))); + query = query.Where(doc => doc.Conditions == null || doc.Conditions.All(cond => cond(request.Context))); } return query.Select(x => x.ToTransition()); diff --git a/tests/DIT.Workflower.Tests/DependencyInjection/DependencyInjectionTests.cs b/tests/DIT.Workflower.Tests/DependencyInjection/DependencyInjectionTests.cs index 1b1be3e..930ce4c 100644 --- a/tests/DIT.Workflower.Tests/DependencyInjection/DependencyInjectionTests.cs +++ b/tests/DIT.Workflower.Tests/DependencyInjection/DependencyInjectionTests.cs @@ -1,5 +1,4 @@ -using DIT.Workflower.DependencyInjection.Abstractions; -using DIT.Workflower.DependencyInjection.Extensions; +using DIT.Workflower.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection; namespace DIT.Workflower.Tests.DependencyInjection; @@ -49,7 +48,6 @@ public class DependencyInjectionTests Assert.NotNull(v1); Assert.NotNull(v2); - Assert.Single(v1!.GetAllowedTransitions(PhoneState.Idle)); Assert.Single(v2!.GetAllowedTransitions(PhoneState.Idle));