Refactor C# expression APIs

This commit is contained in:
Sipke Schoorstra 2023-11-03 22:01:19 +01:00
parent 5d1a1aaf86
commit ab32474c29
7 changed files with 117 additions and 48 deletions

View file

@ -26,7 +26,7 @@ public class RunCSharp : CodeActivity<object?>
{
Script = new Input<string>(script);
}
/// <summary>
/// A list of possible outcomes. Use "SetOutcome(string)" to set the outcome. Use "SetOutcomes(params string[])" to set multiple outcomes.
/// </summary>
@ -63,7 +63,7 @@ public class RunCSharp : CodeActivity<object?>
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);

View file

@ -19,10 +19,13 @@ public class GenerateWorkflowVariableAccessors : INotificationHandler<Evaluating
var expressionExecutionContext = notification.Context;
var variables = expressionExecutionContext.GetVariablesInScope().ToList();
var sb = new StringBuilder();
sb.AppendLine("public partial class WorkflowVariablesWrapper {");
sb.AppendLine("\tpublic WorkflowVariablesWrapper(ExecutionContextProxy executionContext) => 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<T>(string name) => ExecutionContext.GetVariable<T>(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<Evaluating
var friendlyTypeName = GetFriendlyTypeName(variableType);
sb.AppendLine($"\tpublic {friendlyTypeName} {variableName}");
sb.AppendLine("\t{");
sb.AppendLine($"\t\tget => 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;
}

View file

@ -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);
}
/// <summary>
/// Provides access to activity outcomes.
/// </summary>
public OutcomeProxy Outcome { get; set; }
/// <summary>
/// Provides access to activity outputs.
/// </summary>
public OutputProxy Output { get; set; }
/// <summary>
/// Provides access to workflow inputs.
/// </summary>
public InputProxy Input { get; set; }
/// <summary>
/// Gets the current execution context.
/// </summary>
@ -37,35 +54,5 @@ public partial class Globals
set => ExpressionExecutionContext.GetWorkflowExecutionContext().CorrelationId = value;
}
/// <summary>
/// Gets the value of the specified variable.
/// </summary>
public T? GetVariable<T>(string name) => ExpressionExecutionContext.GetVariableInScope(name).ConvertTo<T>();
/// <summary>
/// Sets the value of the specified variable.
/// </summary>
public void SetVariable(string name, object? value) => ExpressionExecutionContext.SetVariable(name, value);
/// <summary>
/// Gets the value of the specified input.
/// </summary>
/// <param name="name">The name of the input.</param>
/// <returns>The value of the input.</returns>
public object? GetInput(string name) => ExpressionExecutionContext.GetInput(name);
/// <summary>
/// Gets the value of the specified output.
/// </summary>
/// <param name="activityIdOrName">The ID or name of the activity that produced the output.</param>
/// <param name="outputName">The name of the output.</param>
/// <returns>The value of the output.</returns>
public object? GetOutputFrom(string activityIdOrName, string? outputName = default) => ExpressionExecutionContext.GetOutput(activityIdOrName, outputName);
/// <summary>
/// Gets the result of the last activity that executed.
/// </summary>
public object? GetLastResult() => ExpressionExecutionContext.GetLastResult();
private ExpressionExecutionContext ExpressionExecutionContext { get; }
}

View file

@ -0,0 +1,30 @@
using Elsa.Expressions.Models;
using Elsa.Extensions;
namespace Elsa.CSharp.Models;
/// <summary>
/// Provides access to workflow inputs.
/// </summary>
public class InputProxy
{
private readonly ExpressionExecutionContext _expressionExecutionContext;
/// <summary>
/// Initializes a new instance of the <see cref="InputProxy"/> class.
/// </summary>
public InputProxy(ExpressionExecutionContext expressionExecutionContext)
{
_expressionExecutionContext = expressionExecutionContext;
}
/// <summary>
/// Gets the value of the specified input.
/// </summary>
public object? Get(string name) => _expressionExecutionContext.GetInput(name);
/// <summary>
/// Gets the value of the specified input.
/// </summary>
public T? Get<T>(string name) => _expressionExecutionContext.GetInput<T>(name);
}

View file

@ -1,27 +1,32 @@
// ReSharper disable once CheckNamespace
using Elsa.Expressions.Models;
namespace Elsa.CSharp.Models;
public partial class Globals
/// <summary>
/// Provides access to activity outcomes.
/// </summary>
public class OutcomeProxy
{
/// <summary>
/// Gets the key of the outcomes property.
/// </summary>
public static readonly object OutcomePropertiesKey = new();
/// <summary>
/// Sets the outcome of the current activity.
/// Initializes a new instance of the <see cref="OutcomeProxy"/> class.
/// </summary>
/// <param name="outcomeName">The name of the outcome.</param>
public void SetOutcome(string outcomeName)
public OutcomeProxy(ExpressionExecutionContext expressionExecutionContext)
{
ExpressionExecutionContext.TransientProperties[OutcomePropertiesKey] = new[] { outcomeName };
ExpressionExecutionContext = expressionExecutionContext;
}
private ExpressionExecutionContext ExpressionExecutionContext { get; }
/// <summary>
/// Sets the outcome of the current activity.
/// </summary>
/// <param name="outcomeNames">The names of the outcomes.</param>
public void SetOutcomes(params string[] outcomeNames)
public void Set(params string[] outcomeNames)
{
ExpressionExecutionContext.TransientProperties[OutcomePropertiesKey] = outcomeNames;
}

View file

@ -0,0 +1,42 @@
using Elsa.Expressions.Helpers;
using Elsa.Expressions.Models;
using Elsa.Extensions;
namespace Elsa.CSharp.Models;
/// <summary>
/// Provides access to activity outputs.
/// </summary>
public class OutputProxy
{
private readonly ExpressionExecutionContext _expressionExecutionContext;
/// <summary>
/// Initializes a new instance of the <see cref="OutputProxy"/> class.
/// </summary>
public OutputProxy(ExpressionExecutionContext expressionExecutionContext)
{
_expressionExecutionContext = expressionExecutionContext;
}
/// <summary>
/// Gets the value of the specified output.
/// </summary>
/// <param name="activityIdOrName">The ID or name of the activity that produced the output.</param>
/// <param name="outputName">The name of the output.</param>
/// <returns>The value of the output.</returns>
public object? Get(string activityIdOrName, string? outputName = default) => _expressionExecutionContext.GetOutput(activityIdOrName, outputName);
/// <summary>
/// Gets the value of the specified output.
/// </summary>
/// <param name="activityIdOrName">The ID or name of the activity that produced the output.</param>
/// <param name="outputName">The name of the output.</param>
/// <returns>The value of the output.</returns>
public T? Get<T>(string activityIdOrName, string? outputName = default) => Get(activityIdOrName, outputName).ConvertTo<T>();
/// <summary>
/// Gets the result of the last activity that executed.
/// </summary>
public object? LastResult => _expressionExecutionContext.GetLastResult();
}

View file

@ -332,6 +332,8 @@ public static class ExpressionExecutionContextExtensions
return input.TryGetValue(name, out var value) ? value : default;
}
/// <summary>
/// Returns the value of the specified input.
/// </summary>