Fix output accessors and add tests
This commit is contained in:
parent
e3d8624e66
commit
003bf4e335
|
|
@ -66,7 +66,7 @@ public static class ActivityExecutionContextExtensions
|
|||
public static void SetResult(this ActivityExecutionContext context, object? value)
|
||||
{
|
||||
var activity = context.Activity as IActivityWithResult ?? throw new Exception($"Cannot set result on activity {context.Activity.Id} because it does not implement {nameof(IActivityWithResult)}.");
|
||||
context.Set(activity.Result, value);
|
||||
context.Set(activity.Result, value, "Result");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -311,15 +311,6 @@ public static class ActivityExecutionContextExtensions
|
|||
public static IEnumerable<ActivityExecutionContext> GetChildren(this ActivityExecutionContext context) =>
|
||||
context.WorkflowExecutionContext.ActiveActivityExecutionContexts.Where(x => x.ParentActivityExecutionContext == context);
|
||||
|
||||
// /// <summary>
|
||||
// /// Removes all child <see cref="ActivityExecutionContext"/> objects.
|
||||
// /// </summary>
|
||||
// public static async Task RemoveChildrenAsync(this ActivityExecutionContext context)
|
||||
// {
|
||||
// // Detach child activity execution contexts.
|
||||
// await context.WorkflowExecutionContext.RemoveActivityExecutionContextsAsync(context.GetChildren());
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Send a signal up the current hierarchy of ancestors.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System.Linq.Expressions;
|
|||
using System.Reflection;
|
||||
using Elsa.Expressions.Helpers;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Contracts;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
using Elsa.Workflows.Core.Services;
|
||||
|
|
@ -61,16 +62,40 @@ public static class ActivityExtensions
|
|||
/// <summary>
|
||||
/// Gets the output with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="activity">The activity.</param>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="activity">The activity to get the output from.</param>
|
||||
/// <param name="context">The workflow execution context.</param>
|
||||
/// <param name="outputName">Name of the output.</param>
|
||||
/// <returns>The output value.</returns>
|
||||
public static object? GetOutput(this IActivity activity, WorkflowExecutionContext context, string? outputName = default)
|
||||
{
|
||||
var workflowExecutionContext = context;
|
||||
var outputRegister = workflowExecutionContext.GetActivityOutputRegister();
|
||||
var output = outputRegister.FindOutputByActivityId(activity.Id, outputName);
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the output with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="activity">The activity to get the output from.</param>
|
||||
/// <param name="context">The activity execution context.</param>
|
||||
/// <param name="outputName">Name of the output.</param>
|
||||
/// <returns>The output value.</returns>
|
||||
public static object? GetOutput(this IActivity activity, ActivityExecutionContext context, string? outputName = default)
|
||||
{
|
||||
return activity.GetOutput(context.WorkflowExecutionContext, outputName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the output with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="activity">The activity to get the output from.</param>
|
||||
/// <param name="context">The expression execution context.</param>
|
||||
/// <param name="outputName">Name of the output.</param>
|
||||
/// <returns>The output value.</returns>
|
||||
public static object? GetOutput(this IActivity activity, ExpressionExecutionContext context, string? outputName = default)
|
||||
{
|
||||
var workflowExecutionContext = context.GetWorkflowExecutionContext();
|
||||
var outputRegister = workflowExecutionContext.GetActivityOutputRegister();
|
||||
var output = outputRegister.FindOutputByActivityInstanceId(context.GetActivityExecutionContext().Id, outputName);
|
||||
return output;
|
||||
return activity.GetOutput(context.GetWorkflowExecutionContext(), outputName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -81,11 +106,24 @@ public static class ActivityExtensions
|
|||
/// <param name="outputName">Name of the output.</param>
|
||||
/// <typeparam name="T">The type of the output.</typeparam>
|
||||
/// <returns>The output value.</returns>
|
||||
public static T? GetOutput<T>(this IActivity activity, ExpressionExecutionContext context, string outputName)
|
||||
public static T? GetOutput<T>(this IActivity activity, ActivityExecutionContext context, string outputName)
|
||||
{
|
||||
var outputValue = activity.GetOutput(context, outputName);
|
||||
return outputValue == null ? default! : outputValue.ConvertTo<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the output with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="activity">The activity.</param>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="outputName">Name of the output.</param>
|
||||
/// <typeparam name="T">The type of the output.</typeparam>
|
||||
/// <returns>The output value.</returns>
|
||||
public static T? GetOutput<T>(this IActivity activity, ExpressionExecutionContext context, string outputName)
|
||||
{
|
||||
return activity.GetOutput<T>(context.GetActivityExecutionContext(), outputName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the output with the specified name.
|
||||
|
|
@ -96,7 +134,7 @@ public static class ActivityExtensions
|
|||
/// <typeparam name="TActivity">The type of the activity.</typeparam>
|
||||
/// <typeparam name="T">The type of the output.</typeparam>
|
||||
/// <returns>The output value.</returns>
|
||||
public static T? GetOutput<TActivity, T>(this TActivity activity, ExpressionExecutionContext context, Expression<Func<TActivity, object?>> outputExpression)
|
||||
public static T? GetOutput<TActivity, T>(this TActivity activity, ActivityExecutionContext context, Expression<Func<TActivity, object?>> outputExpression)
|
||||
{
|
||||
var outputName = outputExpression.GetPropertyName();
|
||||
return ((IActivity)activity!).GetOutput<T>(context, outputName);
|
||||
|
|
@ -114,7 +152,7 @@ public static class ActivityExtensions
|
|||
var value = GetResult(activity, context);
|
||||
return value == null ? default! : value.ConvertTo<T>();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Result output of the specified activity.
|
||||
/// </summary>
|
||||
|
|
@ -122,6 +160,17 @@ public static class ActivityExtensions
|
|||
/// <param name="context">The context.</param>
|
||||
/// <returns>The output value.</returns>
|
||||
public static object? GetResult(this IActivity activity, ExpressionExecutionContext context)
|
||||
{
|
||||
return activity.GetResult(context.GetActivityExecutionContext());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Result output of the specified activity.
|
||||
/// </summary>
|
||||
/// <param name="activity">The activity.</param>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <returns>The output value.</returns>
|
||||
public static object? GetResult(this IActivity activity, ActivityExecutionContext context)
|
||||
{
|
||||
return activity.GetOutput(context, ActivityOutputRegister.DefaultOutputName);
|
||||
}
|
||||
|
|
@ -132,7 +181,7 @@ public static class ActivityExtensions
|
|||
/// <param name="context">The context.</param>
|
||||
/// <param name="activity">The activity.</param>
|
||||
/// <returns>The output value.</returns>
|
||||
public static object? GetResult(this ExpressionExecutionContext context, IActivity activity)
|
||||
public static object? GetResult(this ActivityExecutionContext context, IActivity activity)
|
||||
{
|
||||
return activity.GetOutput(context, ActivityOutputRegister.DefaultOutputName);
|
||||
}
|
||||
|
|
@ -143,7 +192,7 @@ public static class ActivityExtensions
|
|||
/// <param name="context">The context.</param>
|
||||
public static T? GetLastResult<T>(this ExpressionExecutionContext context)
|
||||
{
|
||||
var value = GetLastResult(context);
|
||||
var value = GetLastResult(context.GetWorkflowExecutionContext());
|
||||
return value == null ? default! : value.ConvertTo<T>();
|
||||
}
|
||||
|
||||
|
|
@ -151,10 +200,18 @@ public static class ActivityExtensions
|
|||
/// Gets the result of the last activity.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
public static object? GetLastResult(this ExpressionExecutionContext context)
|
||||
public static object? GetLastResult(this ActivityExecutionContext context)
|
||||
{
|
||||
var workflowExecutionContext = context.GetWorkflowExecutionContext();
|
||||
return workflowExecutionContext.GetLastActivityResult();
|
||||
return context.WorkflowExecutionContext.GetLastResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the result of the last activity.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
public static object? GetLastResult(this WorkflowExecutionContext context)
|
||||
{
|
||||
return context.GetLastActivityResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Memory;
|
||||
|
|
@ -19,7 +20,7 @@ public static class OutputExtensions
|
|||
/// <summary>
|
||||
/// Sets the output to the specified value.
|
||||
/// </summary>
|
||||
public static void Set<T>(this Output<T>? output, ActivityExecutionContext context, T? value) => context.Set(output, value);
|
||||
public static void Set<T>(this Output<T>? output, ActivityExecutionContext context, T? value, [CallerArgumentExpression("output")] string? outputName = default) => context.Set(output, value, outputName);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the output to the specified value.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Memory;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
|
||||
namespace Elsa.IntegrationTests.Scenarios.ActivityOutputs;
|
||||
|
||||
public class SumActivity : CodeActivity<int>
|
||||
{
|
||||
public SumActivity(Variable<int> a, Variable<int> b)
|
||||
{
|
||||
A = new(a);
|
||||
B = new(b);
|
||||
}
|
||||
|
||||
public Input<int> A { get; set; }
|
||||
public Input<int> B { get; set; }
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
var input1 = A.Get(context);
|
||||
var input2 = B.Get(context);
|
||||
var result = input1 + input2;
|
||||
|
||||
// All three work.
|
||||
Result.Set(context, result);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Activities;
|
||||
using Elsa.Workflows.Core.Contracts;
|
||||
using Elsa.Workflows.Core.Memory;
|
||||
|
||||
namespace Elsa.IntegrationTests.Scenarios.ActivityOutputs;
|
||||
|
||||
public class SumWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var a = new Variable<int>();
|
||||
var b = new Variable<int>();
|
||||
|
||||
var sumActivity = new SumActivity(a, b);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Variables = { a, b },
|
||||
Activities =
|
||||
{
|
||||
new Inline(context => a.Set(context, 4)),
|
||||
new Inline(context => b.Set(context, 6)),
|
||||
sumActivity,
|
||||
new WriteLine(context => $"The result of {a.Get(context)} and {b.Get(context)} is {sumActivity.GetResult<int>(context)}."),
|
||||
new WriteLine(context => $"The last result is {context.GetLastResult<int>()}."),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Core.Contracts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.IntegrationTests.Scenarios.ActivityOutputs;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
var services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Activity outputs can be accessed from other activities.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _workflowRunner.RunAsync<SumWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[]
|
||||
{
|
||||
"The result of 4 and 6 is 10.",
|
||||
"The last result is 10."
|
||||
}, lines);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue