From ab32474c29c140ea2289709bdc2df8303baf7c7c Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Fri, 3 Nov 2023 22:01:19 +0100 Subject: [PATCH] Refactor C# expression APIs --- .../Activities/RunCSharp/RunCSharp.cs | 4 +- .../GenerateWorkflowVariableAccessors.cs | 15 +++--- src/modules/Elsa.CSharp/Models/Globals.cs | 49 +++++++------------ src/modules/Elsa.CSharp/Models/InputProxy.cs | 30 ++++++++++++ .../OutcomeProxy.cs} | 23 +++++---- src/modules/Elsa.CSharp/Models/OutputProxy.cs | 42 ++++++++++++++++ .../ExpressionExecutionContextExtensions.cs | 2 + 7 files changed, 117 insertions(+), 48 deletions(-) create mode 100644 src/modules/Elsa.CSharp/Models/InputProxy.cs rename src/modules/Elsa.CSharp/{Activities/RunCSharp/ExecutionContextProxy.cs => Models/OutcomeProxy.cs} (50%) create mode 100644 src/modules/Elsa.CSharp/Models/OutputProxy.cs diff --git a/src/modules/Elsa.CSharp/Activities/RunCSharp/RunCSharp.cs b/src/modules/Elsa.CSharp/Activities/RunCSharp/RunCSharp.cs index e44bdf411..c8a5c6e0f 100644 --- a/src/modules/Elsa.CSharp/Activities/RunCSharp/RunCSharp.cs +++ b/src/modules/Elsa.CSharp/Activities/RunCSharp/RunCSharp.cs @@ -26,7 +26,7 @@ public class RunCSharp : CodeActivity { Script = new Input(script); } - + /// /// A list of possible outcomes. Use "SetOutcome(string)" to set the outcome. Use "SetOutcomes(params string[])" to set multiple outcomes. /// @@ -63,7 +63,7 @@ public class RunCSharp : CodeActivity context.Set(Result, result); // Get the outcome or outcomes set by the script, if any. If not set, use "Done". - var outcomes = context.ExpressionExecutionContext.TransientProperties.GetValueOrDefault(Globals.OutcomePropertiesKey, () => new[] { "Done" })!; + var outcomes = context.ExpressionExecutionContext.TransientProperties.GetValueOrDefault(OutcomeProxy.OutcomePropertiesKey, () => new[] { "Done" })!; // Complete the activity with the outcome. await context.CompleteActivityWithOutcomesAsync(outcomes); diff --git a/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs b/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs index 6778813a5..0884b9fc0 100644 --- a/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs +++ b/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs @@ -19,10 +19,13 @@ public class GenerateWorkflowVariableAccessors : INotificationHandler ExecutionContext = executionContext;"); + sb.AppendLine("public partial class WorkflowVariablesProxy {"); + sb.AppendLine("\tpublic WorkflowVariablesProxy(ExecutionContextProxy executionContext) => ExecutionContext = executionContext;"); sb.AppendLine("\tpublic ExecutionContextProxy ExecutionContext { get; }"); - + sb.AppendLine(); + sb.AppendLine("\tpublic T? Get(string name) => ExecutionContext.GetVariable(name);"); + sb.AppendLine("\tpublic void Set(string name, object? value) => ExecutionContext.SetVariable(name, value);"); + sb.AppendLine(); foreach (var variable in variables) { var variableName = variable.Name.Pascalize(); @@ -30,13 +33,13 @@ public class GenerateWorkflowVariableAccessors : INotificationHandler ExecutionContext.GetVariable<{friendlyTypeName}>(\"{variableName}\");"); - sb.AppendLine($"\t\tset => ExecutionContext.SetVariable(\"{variableName}\", value);"); + sb.AppendLine($"\t\tget => Get<{friendlyTypeName}>(\"{variableName}\");"); + sb.AppendLine($"\t\tset => Set(\"{variableName}\", value);"); sb.AppendLine("\t}"); } sb.AppendLine("}"); - sb.AppendLine("var Variables = new WorkflowVariablesWrapper(ExecutionContext);"); + sb.AppendLine("var Variable = new WorkflowVariablesProxy(ExecutionContext);"); notification.AppendScript(sb.ToString()); return Task.CompletedTask; } diff --git a/src/modules/Elsa.CSharp/Models/Globals.cs b/src/modules/Elsa.CSharp/Models/Globals.cs index 0f674409e..6b2c985af 100644 --- a/src/modules/Elsa.CSharp/Models/Globals.cs +++ b/src/modules/Elsa.CSharp/Models/Globals.cs @@ -1,4 +1,3 @@ -using Elsa.Expressions.Helpers; using Elsa.Expressions.Models; using Elsa.Extensions; @@ -16,8 +15,26 @@ public partial class Globals { ExpressionExecutionContext = expressionExecutionContext; ExecutionContext = new ExecutionContextProxy(expressionExecutionContext); + Input = new InputProxy(expressionExecutionContext); + Output = new OutputProxy(expressionExecutionContext); + Outcome = new OutcomeProxy(expressionExecutionContext); } + /// + /// Provides access to activity outcomes. + /// + public OutcomeProxy Outcome { get; set; } + + /// + /// Provides access to activity outputs. + /// + public OutputProxy Output { get; set; } + + /// + /// Provides access to workflow inputs. + /// + public InputProxy Input { get; set; } + /// /// Gets the current execution context. /// @@ -37,35 +54,5 @@ public partial class Globals set => ExpressionExecutionContext.GetWorkflowExecutionContext().CorrelationId = value; } - /// - /// Gets the value of the specified variable. - /// - public T? GetVariable(string name) => ExpressionExecutionContext.GetVariableInScope(name).ConvertTo(); - - /// - /// Sets the value of the specified variable. - /// - public void SetVariable(string name, object? value) => ExpressionExecutionContext.SetVariable(name, value); - - /// - /// Gets the value of the specified input. - /// - /// The name of the input. - /// The value of the input. - public object? GetInput(string name) => ExpressionExecutionContext.GetInput(name); - - /// - /// Gets the value of the specified output. - /// - /// The ID or name of the activity that produced the output. - /// The name of the output. - /// The value of the output. - public object? GetOutputFrom(string activityIdOrName, string? outputName = default) => ExpressionExecutionContext.GetOutput(activityIdOrName, outputName); - - /// - /// Gets the result of the last activity that executed. - /// - public object? GetLastResult() => ExpressionExecutionContext.GetLastResult(); - private ExpressionExecutionContext ExpressionExecutionContext { get; } } \ No newline at end of file diff --git a/src/modules/Elsa.CSharp/Models/InputProxy.cs b/src/modules/Elsa.CSharp/Models/InputProxy.cs new file mode 100644 index 000000000..98b16df40 --- /dev/null +++ b/src/modules/Elsa.CSharp/Models/InputProxy.cs @@ -0,0 +1,30 @@ +using Elsa.Expressions.Models; +using Elsa.Extensions; + +namespace Elsa.CSharp.Models; + +/// +/// Provides access to workflow inputs. +/// +public class InputProxy +{ + private readonly ExpressionExecutionContext _expressionExecutionContext; + + /// + /// Initializes a new instance of the class. + /// + public InputProxy(ExpressionExecutionContext expressionExecutionContext) + { + _expressionExecutionContext = expressionExecutionContext; + } + + /// + /// Gets the value of the specified input. + /// + public object? Get(string name) => _expressionExecutionContext.GetInput(name); + + /// + /// Gets the value of the specified input. + /// + public T? Get(string name) => _expressionExecutionContext.GetInput(name); +} \ No newline at end of file diff --git a/src/modules/Elsa.CSharp/Activities/RunCSharp/ExecutionContextProxy.cs b/src/modules/Elsa.CSharp/Models/OutcomeProxy.cs similarity index 50% rename from src/modules/Elsa.CSharp/Activities/RunCSharp/ExecutionContextProxy.cs rename to src/modules/Elsa.CSharp/Models/OutcomeProxy.cs index a7510216e..9d313b340 100644 --- a/src/modules/Elsa.CSharp/Activities/RunCSharp/ExecutionContextProxy.cs +++ b/src/modules/Elsa.CSharp/Models/OutcomeProxy.cs @@ -1,27 +1,32 @@ -// ReSharper disable once CheckNamespace +using Elsa.Expressions.Models; + namespace Elsa.CSharp.Models; -public partial class Globals +/// +/// Provides access to activity outcomes. +/// +public class OutcomeProxy { /// /// Gets the key of the outcomes property. /// public static readonly object OutcomePropertiesKey = new(); - + /// - /// Sets the outcome of the current activity. + /// Initializes a new instance of the class. /// - /// The name of the outcome. - public void SetOutcome(string outcomeName) + public OutcomeProxy(ExpressionExecutionContext expressionExecutionContext) { - ExpressionExecutionContext.TransientProperties[OutcomePropertiesKey] = new[] { outcomeName }; + ExpressionExecutionContext = expressionExecutionContext; } - + + private ExpressionExecutionContext ExpressionExecutionContext { get; } + /// /// Sets the outcome of the current activity. /// /// The names of the outcomes. - public void SetOutcomes(params string[] outcomeNames) + public void Set(params string[] outcomeNames) { ExpressionExecutionContext.TransientProperties[OutcomePropertiesKey] = outcomeNames; } diff --git a/src/modules/Elsa.CSharp/Models/OutputProxy.cs b/src/modules/Elsa.CSharp/Models/OutputProxy.cs new file mode 100644 index 000000000..d4d362b4e --- /dev/null +++ b/src/modules/Elsa.CSharp/Models/OutputProxy.cs @@ -0,0 +1,42 @@ +using Elsa.Expressions.Helpers; +using Elsa.Expressions.Models; +using Elsa.Extensions; + +namespace Elsa.CSharp.Models; + +/// +/// Provides access to activity outputs. +/// +public class OutputProxy +{ + private readonly ExpressionExecutionContext _expressionExecutionContext; + + /// + /// Initializes a new instance of the class. + /// + public OutputProxy(ExpressionExecutionContext expressionExecutionContext) + { + _expressionExecutionContext = expressionExecutionContext; + } + + /// + /// Gets the value of the specified output. + /// + /// The ID or name of the activity that produced the output. + /// The name of the output. + /// The value of the output. + public object? Get(string activityIdOrName, string? outputName = default) => _expressionExecutionContext.GetOutput(activityIdOrName, outputName); + + /// + /// Gets the value of the specified output. + /// + /// The ID or name of the activity that produced the output. + /// The name of the output. + /// The value of the output. + public T? Get(string activityIdOrName, string? outputName = default) => Get(activityIdOrName, outputName).ConvertTo(); + + /// + /// Gets the result of the last activity that executed. + /// + public object? LastResult => _expressionExecutionContext.GetLastResult(); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs index 6a56ead94..6c80b0df6 100644 --- a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs +++ b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs @@ -332,6 +332,8 @@ public static class ExpressionExecutionContextExtensions return input.TryGetValue(name, out var value) ? value : default; } + + /// /// Returns the value of the specified input. ///