Update Workflow builder API with support for property storage providers

This commit is contained in:
Sipke Schoorstra 2021-06-14 13:46:25 +02:00
parent f67140f7e2
commit d787ca34ca
9 changed files with 55 additions and 12 deletions

View file

@ -14,6 +14,7 @@ namespace Elsa.Builders
IActivityBuilder New<T>(
string activityTypeName,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders = default,
IDictionary<string, string>? storageProviders = default,
[CallerLineNumber] int lineNumber = default,
[CallerFilePath] string? sourceFile = default)
where T : class, IActivity;
@ -44,6 +45,7 @@ namespace Elsa.Builders
string activityTypeName,
Action<IActivityBuilder>? branch = default,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders = default,
IDictionary<string, string>? storageProviders = default,
[CallerLineNumber] int lineNumber = default,
[CallerFilePath] string? sourceFile = default)
where T : class, IActivity;

View file

@ -13,6 +13,7 @@ namespace Elsa.Builders
public interface ISetupActivity<T> : ISetupActivity where T : IActivity
{
ISetupActivity<T> Set<TProperty>(Expression<Func<T, TProperty?>> propertyAccessor, Func<ActivityExecutionContext, ValueTask<TProperty?>> valueFactory);
ISetupActivity<T> WithStorageFor<TProperty>(Expression<Func<T, TProperty?>> propertyAccessor, string? storageProviderName);
}
public static class SetupActivityExtensions

View file

@ -16,6 +16,7 @@ namespace Elsa.Builders
string activityTypeName,
ICompositeActivityBuilder workflowBuilder,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders,
IDictionary<string, string>? 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<string, IActivityPropertyValueProvider>? PropertyValueProviders { get; protected set; }
public IDictionary<string, string>? StorageProviders { get; }
public IDictionary<string, string> PropertyStorageProviders { get; set; } = new Dictionary<string, string>();
public int LineNumber { get; }
public string? SourceFile { get; }

View file

@ -54,20 +54,22 @@ namespace Elsa.Builders
Type activityType,
string activityTypeName,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders = default,
IDictionary<string, string>? 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<T>(
string activityTypeName,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders = default,
IDictionary<string, string>? 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<T>(
string activityTypeName,
@ -82,7 +84,9 @@ namespace Elsa.Builders
x => x.Key,
x => (IActivityPropertyValueProvider) new DelegateActivityPropertyValueProvider(x.Value));
return New<T>(activityTypeName, valueProviders, lineNumber, sourceFile);
var storageProviders = propertyValuesBuilder.StorageProviders;
return New<T>(activityTypeName, valueProviders, storageProviders, lineNumber, sourceFile);
}
public IActivityBuilder StartWith<T>(
@ -98,7 +102,7 @@ namespace Elsa.Builders
public IActivityBuilder StartWith<T>(string activityTypeName, Action<IActivityBuilder>? branch = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default)
where T : class, IActivity =>
Add<T>(activityTypeName, branch, null, lineNumber, sourceFile);
Add<T>(activityTypeName, branch, null, null, lineNumber, sourceFile);
public IActivityBuilder Add<T>(
string activityTypeName,
@ -115,11 +119,12 @@ namespace Elsa.Builders
string activityTypeName,
Action<IActivityBuilder>? branch = default,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders = default,
IDictionary<string, string>? 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<IActivityBuilder> 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}";
}
}

View file

@ -11,9 +11,10 @@ namespace Elsa.Builders
public static IActivityBuilder New<T>(
this ICompositeActivityBuilder compositeActivityBuilder,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders = default,
IDictionary<string, string>? storageProviders = default,
[CallerLineNumber] int lineNumber = default,
[CallerFilePath] string? sourceFile = default)
where T : class, IActivity => compositeActivityBuilder.New<T>(typeof(T).Name, propertyValueProviders, lineNumber, sourceFile);
where T : class, IActivity => compositeActivityBuilder.New<T>(typeof(T).Name, propertyValueProviders, storageProviders, lineNumber, sourceFile);
public static IActivityBuilder New<T>(
this ICompositeActivityBuilder compositeActivityBuilder,
@ -45,8 +46,9 @@ namespace Elsa.Builders
this ICompositeActivityBuilder compositeActivityBuilder,
Action<IActivityBuilder>? branch = default,
IDictionary<string, IActivityPropertyValueProvider>? propertyValueProviders = default,
IDictionary<string, string>? storageProviders = default,
[CallerLineNumber] int lineNumber = default,
[CallerFilePath] string? sourceFile = default)
where T : class, IActivity => compositeActivityBuilder.Add<T>(typeof(T).Name, branch, propertyValueProviders, lineNumber, sourceFile);
where T : class, IActivity => compositeActivityBuilder.Add<T>(typeof(T).Name, branch, propertyValueProviders, storageProviders, lineNumber, sourceFile);
}
}

View file

@ -35,7 +35,7 @@ namespace Elsa.Builders
public IActivityBuilder Then<T>(string activityTypeName, Action<IActivityBuilder>? branch = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default)
where T : class, IActivity
{
var activityBuilder = WorkflowBuilder.Add<T>(activityTypeName, branch, null, lineNumber, sourceFile);
var activityBuilder = WorkflowBuilder.Add<T>(activityTypeName, branch, null, null, lineNumber, sourceFile);
Then(activityBuilder);
return activityBuilder;
}

View file

@ -10,6 +10,7 @@ namespace Elsa.Builders
public class SetupActivity<T> : ISetupActivity<T> where T : IActivity
{
public IDictionary<string, Func<ActivityExecutionContext, ValueTask<object?>>> ValueProviders { get; } = new Dictionary<string, Func<ActivityExecutionContext, ValueTask<object?>>>();
public IDictionary<string, string> StorageProviders { get; } = new Dictionary<string, string>();
public ISetupActivity<T> Set<TProperty>(Expression<Func<T, TProperty?>> propertyAccessor, Func<ActivityExecutionContext, ValueTask<TProperty?>> valueFactory)
{
@ -17,5 +18,17 @@ namespace Elsa.Builders
ValueProviders[propertyInfo.Name] = async context => await valueFactory(context);
return this;
}
public ISetupActivity<T> WithStorageFor<TProperty>(Expression<Func<T, TProperty?>> propertyAccessor, string? storageProviderName)
{
var propertyInfo = propertyAccessor.GetProperty()!;
if(storageProviderName != null)
StorageProviders[propertyInfo.Name] = storageProviderName;
else
StorageProviders.Remove(propertyInfo.Name);
return this;
}
}
}

View file

@ -178,5 +178,8 @@ namespace Elsa.Builders
compositeRoot.Connections,
compositeRoot.ActivityPropertyProviders);
}
// Do not qualify root activities.
protected override string? GetCompositeName(string? activityName) => activityName;
}
}

View file

@ -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<T> WithTransientStorageFor<T, TProperty>(this ISetupActivity<T> builder, Expression<Func<T, TProperty?>> propertyAccessor) where T : IActivity => builder.WithStorageFor(propertyAccessor, "Transient");
public static ISetupActivity<T> WithWorkflowInstanceStorageFor<T, TProperty>(this ISetupActivity<T> builder, Expression<Func<T, TProperty?>> propertyAccessor) where T : IActivity => builder.WithStorageFor(propertyAccessor, "WorkflowInstance");
}
}