From d787ca34ca07153cabd3e06b3f059bcd0bc4d5b2 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 14 Jun 2021 13:46:25 +0200 Subject: [PATCH] Update Workflow builder API with support for property storage providers --- .../Builders/ICompositeActivityBuilder.cs | 2 ++ .../Builders/ISetupActivity.cs | 1 + .../Elsa.Core/Builders/ActivityBuilder.cs | 3 +++ .../Builders/CompositeActivityBuilder.cs | 24 ++++++++++++------- .../CompositeActivityBuilderExtensions.cs | 6 +++-- src/core/Elsa.Core/Builders/OutcomeBuilder.cs | 2 +- src/core/Elsa.Core/Builders/SetupActivity.cs | 13 ++++++++++ .../Elsa.Core/Builders/WorkflowBuilder.cs | 3 +++ .../Extensions/SetupActivityExtensions.cs | 13 ++++++++++ 9 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 src/core/Elsa.Core/Extensions/SetupActivityExtensions.cs diff --git a/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs b/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs index d87f6b695..effd47d0f 100644 --- a/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs +++ b/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs @@ -14,6 +14,7 @@ namespace Elsa.Builders IActivityBuilder New( string activityTypeName, IDictionary? propertyValueProviders = default, + IDictionary? storageProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity; @@ -44,6 +45,7 @@ namespace Elsa.Builders string activityTypeName, Action? branch = default, IDictionary? propertyValueProviders = default, + IDictionary? storageProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity; diff --git a/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs b/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs index 3c780f2b5..d8dfa98a2 100644 --- a/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs +++ b/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs @@ -13,6 +13,7 @@ namespace Elsa.Builders public interface ISetupActivity : ISetupActivity where T : IActivity { ISetupActivity Set(Expression> propertyAccessor, Func> valueFactory); + ISetupActivity WithStorageFor(Expression> propertyAccessor, string? storageProviderName); } public static class SetupActivityExtensions diff --git a/src/core/Elsa.Core/Builders/ActivityBuilder.cs b/src/core/Elsa.Core/Builders/ActivityBuilder.cs index 9a07c783b..a845a3f96 100644 --- a/src/core/Elsa.Core/Builders/ActivityBuilder.cs +++ b/src/core/Elsa.Core/Builders/ActivityBuilder.cs @@ -16,6 +16,7 @@ namespace Elsa.Builders string activityTypeName, ICompositeActivityBuilder workflowBuilder, IDictionary? propertyValueProviders, + IDictionary? storageProviders, int lineNumber, string? sourceFile) { @@ -23,6 +24,7 @@ namespace Elsa.Builders ActivityTypeName = activityTypeName; WorkflowBuilder = workflowBuilder; PropertyValueProviders = propertyValueProviders; + StorageProviders = storageProviders; LineNumber = lineNumber; SourceFile = sourceFile; } @@ -42,6 +44,7 @@ namespace Elsa.Builders public bool LoadWorkflowContextEnabled { get; set; } public bool SaveWorkflowContextEnabled { get; set; } public IDictionary? PropertyValueProviders { get; protected set; } + public IDictionary? StorageProviders { get; } public IDictionary PropertyStorageProviders { get; set; } = new Dictionary(); public int LineNumber { get; } public string? SourceFile { get; } diff --git a/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs b/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs index 2743c45b4..4a163124b 100644 --- a/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs +++ b/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs @@ -54,20 +54,22 @@ namespace Elsa.Builders Type activityType, string activityTypeName, IDictionary? propertyValueProviders = default, + IDictionary? storageProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) { - var activityBuilder = new ActivityBuilder(activityType, activityTypeName, this, propertyValueProviders, lineNumber, sourceFile); + var activityBuilder = new ActivityBuilder(activityType, activityTypeName, this, propertyValueProviders, storageProviders, lineNumber, sourceFile); return activityBuilder; } public IActivityBuilder New( string activityTypeName, IDictionary? propertyValueProviders = default, + IDictionary? storageProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity => - New(typeof(T), activityTypeName, propertyValueProviders, lineNumber, sourceFile); + New(typeof(T), activityTypeName, propertyValueProviders, storageProviders, lineNumber, sourceFile); public IActivityBuilder New( string activityTypeName, @@ -82,7 +84,9 @@ namespace Elsa.Builders x => x.Key, x => (IActivityPropertyValueProvider) new DelegateActivityPropertyValueProvider(x.Value)); - return New(activityTypeName, valueProviders, lineNumber, sourceFile); + var storageProviders = propertyValuesBuilder.StorageProviders; + + return New(activityTypeName, valueProviders, storageProviders, lineNumber, sourceFile); } public IActivityBuilder StartWith( @@ -98,7 +102,7 @@ namespace Elsa.Builders public IActivityBuilder StartWith(string activityTypeName, Action? branch = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity => - Add(activityTypeName, branch, null, lineNumber, sourceFile); + Add(activityTypeName, branch, null, null, lineNumber, sourceFile); public IActivityBuilder Add( string activityTypeName, @@ -115,11 +119,12 @@ namespace Elsa.Builders string activityTypeName, Action? branch = default, IDictionary? propertyValueProviders = default, + IDictionary? storageProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity { - var activityBuilder = new ActivityBuilder(typeof(T), activityTypeName, this, propertyValueProviders, lineNumber, sourceFile); + var activityBuilder = new ActivityBuilder(typeof(T), activityTypeName, this, propertyValueProviders, storageProviders, lineNumber, sourceFile); return Add(activityBuilder, branch); } @@ -215,6 +220,8 @@ namespace Elsa.Builders return compositeActivityBlueprint; } + + protected virtual string? GetCompositeName(string? activityName) => activityName == null ? null : $"{ActivityId}:{activityName}"; private void BuildCompositeActivities( IEnumerable compositeActivityBuilders, @@ -237,9 +244,9 @@ namespace Elsa.Builders connections.AddRange(compositeActivityBlueprint.Connections.Select(x => new Connection(activityDictionary[x.Source.Activity.Id], activityDictionary[x.Target.Activity.Id], x.Source.Outcome))); activityPropertyProviders.AddRange(compositeActivityBlueprint.ActivityPropertyProviders); - compositeActivityBlueprint.Activities = compositeActivityBlueprint.Activities; - compositeActivityBlueprint.Connections = compositeActivityBlueprint.Connections; - compositeActivityBlueprint.ActivityPropertyProviders = compositeActivityBlueprint.ActivityPropertyProviders; + // compositeActivityBlueprint.Activities = compositeActivityBlueprint.Activities; + // compositeActivityBlueprint.Connections = compositeActivityBlueprint.Connections; + // compositeActivityBlueprint.ActivityPropertyProviders = compositeActivityBlueprint.ActivityPropertyProviders; // Connect the composite activity to its starting activities. var startActivities = _startingActivitiesProvider.GetStartActivities(compositeActivityBlueprint).ToList(); @@ -257,6 +264,5 @@ namespace Elsa.Builders builder.SaveWorkflowContextEnabled, builder.PropertyStorageProviders, builder.Source); } - private string? GetCompositeName(string? activityName) => activityName == null ? null : $"{ActivityId}:{activityName}"; } } \ No newline at end of file diff --git a/src/core/Elsa.Core/Builders/CompositeActivityBuilderExtensions.cs b/src/core/Elsa.Core/Builders/CompositeActivityBuilderExtensions.cs index 8910f4475..9a55a55fa 100644 --- a/src/core/Elsa.Core/Builders/CompositeActivityBuilderExtensions.cs +++ b/src/core/Elsa.Core/Builders/CompositeActivityBuilderExtensions.cs @@ -11,9 +11,10 @@ namespace Elsa.Builders public static IActivityBuilder New( this ICompositeActivityBuilder compositeActivityBuilder, IDictionary? propertyValueProviders = default, + IDictionary? storageProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) - where T : class, IActivity => compositeActivityBuilder.New(typeof(T).Name, propertyValueProviders, lineNumber, sourceFile); + where T : class, IActivity => compositeActivityBuilder.New(typeof(T).Name, propertyValueProviders, storageProviders, lineNumber, sourceFile); public static IActivityBuilder New( this ICompositeActivityBuilder compositeActivityBuilder, @@ -45,8 +46,9 @@ namespace Elsa.Builders this ICompositeActivityBuilder compositeActivityBuilder, Action? branch = default, IDictionary? propertyValueProviders = default, + IDictionary? storageProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) - where T : class, IActivity => compositeActivityBuilder.Add(typeof(T).Name, branch, propertyValueProviders, lineNumber, sourceFile); + where T : class, IActivity => compositeActivityBuilder.Add(typeof(T).Name, branch, propertyValueProviders, storageProviders, lineNumber, sourceFile); } } \ No newline at end of file diff --git a/src/core/Elsa.Core/Builders/OutcomeBuilder.cs b/src/core/Elsa.Core/Builders/OutcomeBuilder.cs index 081bfeddc..f32586977 100644 --- a/src/core/Elsa.Core/Builders/OutcomeBuilder.cs +++ b/src/core/Elsa.Core/Builders/OutcomeBuilder.cs @@ -35,7 +35,7 @@ namespace Elsa.Builders public IActivityBuilder Then(string activityTypeName, Action? branch = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity { - var activityBuilder = WorkflowBuilder.Add(activityTypeName, branch, null, lineNumber, sourceFile); + var activityBuilder = WorkflowBuilder.Add(activityTypeName, branch, null, null, lineNumber, sourceFile); Then(activityBuilder); return activityBuilder; } diff --git a/src/core/Elsa.Core/Builders/SetupActivity.cs b/src/core/Elsa.Core/Builders/SetupActivity.cs index f47d99239..6c530e09a 100644 --- a/src/core/Elsa.Core/Builders/SetupActivity.cs +++ b/src/core/Elsa.Core/Builders/SetupActivity.cs @@ -10,6 +10,7 @@ namespace Elsa.Builders public class SetupActivity : ISetupActivity where T : IActivity { public IDictionary>> ValueProviders { get; } = new Dictionary>>(); + public IDictionary StorageProviders { get; } = new Dictionary(); public ISetupActivity Set(Expression> propertyAccessor, Func> valueFactory) { @@ -17,5 +18,17 @@ namespace Elsa.Builders ValueProviders[propertyInfo.Name] = async context => await valueFactory(context); return this; } + + public ISetupActivity WithStorageFor(Expression> propertyAccessor, string? storageProviderName) + { + var propertyInfo = propertyAccessor.GetProperty()!; + + if(storageProviderName != null) + StorageProviders[propertyInfo.Name] = storageProviderName; + else + StorageProviders.Remove(propertyInfo.Name); + + return this; + } } } \ No newline at end of file diff --git a/src/core/Elsa.Core/Builders/WorkflowBuilder.cs b/src/core/Elsa.Core/Builders/WorkflowBuilder.cs index 273d57a8e..dd8f6d0db 100644 --- a/src/core/Elsa.Core/Builders/WorkflowBuilder.cs +++ b/src/core/Elsa.Core/Builders/WorkflowBuilder.cs @@ -178,5 +178,8 @@ namespace Elsa.Builders compositeRoot.Connections, compositeRoot.ActivityPropertyProviders); } + + // Do not qualify root activities. + protected override string? GetCompositeName(string? activityName) => activityName; } } \ No newline at end of file diff --git a/src/core/Elsa.Core/Extensions/SetupActivityExtensions.cs b/src/core/Elsa.Core/Extensions/SetupActivityExtensions.cs new file mode 100644 index 000000000..d0828a568 --- /dev/null +++ b/src/core/Elsa.Core/Extensions/SetupActivityExtensions.cs @@ -0,0 +1,13 @@ +using System; +using System.Linq.Expressions; +using Elsa.Builders; +using Elsa.Services; + +namespace Elsa +{ + public static class SetupActivityExtensions + { + public static ISetupActivity WithTransientStorageFor(this ISetupActivity builder, Expression> propertyAccessor) where T : IActivity => builder.WithStorageFor(propertyAccessor, "Transient"); + public static ISetupActivity WithWorkflowInstanceStorageFor(this ISetupActivity builder, Expression> propertyAccessor) where T : IActivity => builder.WithStorageFor(propertyAccessor, "WorkflowInstance"); + } +} \ No newline at end of file