diff --git a/Samples.sln b/Samples.sln index f34c9d386..26cff5fa2 100644 --- a/Samples.sln +++ b/Samples.sln @@ -114,6 +114,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.ProgrammaticCo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.DeclarativeCompositeActivitiesConsole", "src\samples\Elsa.Samples.DeclarativeCompositeActivitiesConsole\Elsa.Samples.DeclarativeCompositeActivitiesConsole.csproj", "{E422689B-9F82-45B6-BE14-62B4EEF43B57}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.GoBackConsole", "src\samples\Elsa.Samples.GoBackConsole\Elsa.Samples.GoBackConsole.csproj", "{F4454030-8295-4575-A54C-D816235173C5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -273,6 +275,10 @@ Global {E422689B-9F82-45B6-BE14-62B4EEF43B57}.Debug|Any CPU.Build.0 = Debug|Any CPU {E422689B-9F82-45B6-BE14-62B4EEF43B57}.Release|Any CPU.ActiveCfg = Release|Any CPU {E422689B-9F82-45B6-BE14-62B4EEF43B57}.Release|Any CPU.Build.0 = Release|Any CPU + {F4454030-8295-4575-A54C-D816235173C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4454030-8295-4575-A54C-D816235173C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4454030-8295-4575-A54C-D816235173C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4454030-8295-4575-A54C-D816235173C5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -326,6 +332,7 @@ Global {1E5E1669-AEC9-4DA9-9A3D-3D405101A246} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} {CC39E9F8-72D2-4A5B-846B-E2764DFE1C19} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} {E422689B-9F82-45B6-BE14-62B4EEF43B57} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} + {F4454030-8295-4575-A54C-D816235173C5} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158} diff --git a/src/core/Elsa.Core/Activities/ControlFlow/IfElse/IfElseBuilderExtensions.cs b/src/core/Elsa.Core/Activities/ControlFlow/IfElse/IfElseBuilderExtensions.cs index 66443b90f..7a42681e9 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/IfElse/IfElseBuilderExtensions.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/IfElse/IfElseBuilderExtensions.cs @@ -7,16 +7,15 @@ namespace Elsa.Activities.ControlFlow { public static class IfElseBuilderExtensions { - public static IActivityBuilder IfElse(this IBuilder builder, Action>? setup = default, Action? ifElse = default) + public static IActivityBuilder IfElse(this IBuilder builder, Action>? setup = default, Action? activity = default) { var activityBuilder = builder.Then(setup); - ifElse?.Invoke(activityBuilder); + activity?.Invoke(activityBuilder); return activityBuilder; } - - public static IActivityBuilder IfElse(this IBuilder builder, Action>? setup = default, string? name = default) => builder.Then(setup).WithName(name); - public static IActivityBuilder IfElse(this IBuilder builder, Func condition, string? name = default) => builder.IfElse(activity => activity.Set(x => x.Condition, condition), name); - public static IActivityBuilder IfElse(this IBuilder builder, Func condition, string? name = default) => builder.IfElse(activity => activity.Set(x => x.Condition, condition), name); - public static IActivityBuilder IfElse(this IBuilder builder, bool condition, string? name = default) => builder.IfElse(activity => activity.Set(x => x.Condition, condition), name); + + public static IActivityBuilder IfElse(this IBuilder builder, Func condition, Action? activity = default) => builder.IfElse(x => x.WithCondition(condition), activity); + public static IActivityBuilder IfElse(this IBuilder builder, Func condition, Action? activity = default) => builder.IfElse(x => x.WithCondition(condition), activity); + public static IActivityBuilder IfElse(this IBuilder builder, bool condition, Action? activity = default) => builder.IfElse(x => x.WithCondition(condition), activity); } } \ No newline at end of file diff --git a/src/core/Elsa.Core/ActivityResults/GoBackResult.cs b/src/core/Elsa.Core/ActivityResults/GoBackResult.cs new file mode 100644 index 000000000..15b7f2059 --- /dev/null +++ b/src/core/Elsa.Core/ActivityResults/GoBackResult.cs @@ -0,0 +1,32 @@ +using System.Linq; +using Elsa.Services.Models; + +namespace Elsa.ActivityResults +{ + /// + /// Schedules the previously executed activity, effectively going back one step. + /// + public class GoBackResult : ActivityExecutionResult + { + private readonly int _steps; + private readonly object? _input; + + public GoBackResult(object? input = default, int steps = 1) + { + _input = input; + _steps = steps; + } + + protected override void Execute(ActivityExecutionContext activityExecutionContext) + { + var workflowExecutionContext = activityExecutionContext.WorkflowExecutionContext; + var previousEntry = workflowExecutionContext.ExecutionLog.Skip(_steps).FirstOrDefault(); + + if (previousEntry == null) + return; + + var activityId = previousEntry.ActivityId; + workflowExecutionContext.ScheduleActivity(activityId, _input); + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.GoBackConsole/Activities/BrickWallActivity.cs b/src/samples/Elsa.Samples.GoBackConsole/Activities/BrickWallActivity.cs new file mode 100644 index 000000000..fef22a4b6 --- /dev/null +++ b/src/samples/Elsa.Samples.GoBackConsole/Activities/BrickWallActivity.cs @@ -0,0 +1,18 @@ +using Elsa.ActivityResults; +using Elsa.Services; +using Elsa.Services.Models; + +namespace Elsa.Samples.GoBackConsole.Activities +{ + /// + /// A custom activity that instructs the workflow runner to go back one step under certain conditions. + /// + public class BrickWallActivity : Activity + { + protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context) + { + // Tell the workflow that it hit a brick wall. + return new GoBackResult("Brick Wall"); + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.GoBackConsole/Elsa.Samples.GoBackConsole.csproj b/src/samples/Elsa.Samples.GoBackConsole/Elsa.Samples.GoBackConsole.csproj new file mode 100644 index 000000000..910f7f606 --- /dev/null +++ b/src/samples/Elsa.Samples.GoBackConsole/Elsa.Samples.GoBackConsole.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + enable + + + + + + + + + + + diff --git a/src/samples/Elsa.Samples.GoBackConsole/Program.cs b/src/samples/Elsa.Samples.GoBackConsole/Program.cs new file mode 100644 index 000000000..6156bd012 --- /dev/null +++ b/src/samples/Elsa.Samples.GoBackConsole/Program.cs @@ -0,0 +1,35 @@ +using System.Threading.Tasks; +using Elsa.Samples.GoBackConsole.Activities; +using Elsa.Samples.GoBackConsole.Workflows; +using Elsa.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Samples.GoBackConsole +{ + /// + /// Demonstrates a workflow with a While looping construct. + /// + static class Program + { + private static async Task Main() + { + // Create a service container with Elsa services. + var services = new ServiceCollection() + .AddElsa() + .AddConsoleActivities() + .AddActivity() + .AddWorkflow() + .BuildServiceProvider(); + + // Run startup actions (not needed when registering Elsa with a Host). + var startupRunner = services.GetRequiredService(); + await startupRunner.StartupAsync(); + + // Get a workflow runner. + var workflowRunner = services.GetService(); + + // Execute the workflow. + await workflowRunner.RunWorkflowAsync(); + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.GoBackConsole/Workflows/WalkAroundWorkflow.cs b/src/samples/Elsa.Samples.GoBackConsole/Workflows/WalkAroundWorkflow.cs new file mode 100644 index 000000000..7057e97d6 --- /dev/null +++ b/src/samples/Elsa.Samples.GoBackConsole/Workflows/WalkAroundWorkflow.cs @@ -0,0 +1,30 @@ +using Elsa.Activities.Console; +using Elsa.Activities.ControlFlow; +using Elsa.Builders; +using Elsa.Samples.GoBackConsole.Activities; +using Elsa.Services.Models; + +namespace Elsa.Samples.GoBackConsole.Workflows +{ + public class WalkAroundWorkflow : IWorkflow + { + public void Build(IWorkflowBuilder workflow) + { + workflow + .WriteLine("Taking a stroll...") + .IfElse(context => (string?)context.Input == "Brick Wall", + ifElse => + { + ifElse + .When(IfElse.False) + .WriteLine("Hitting a wall...") + .Then(); + + ifElse + .When(IfElse.True) + .WriteLine("Going around the wall...") + .WriteLine("Made it!"); + }); + } + } +} \ No newline at end of file