elsa-core/src/core/Elsa.Abstractions/Services/CompositeActivity.cs
Sipke Schoorstra 5d8d05aec5 Stash
2021-03-26 11:40:22 +01:00

96 lines
3.2 KiB
C#

using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using Elsa.ActivityResults;
using Elsa.Builders;
using Elsa.Models;
using Elsa.Services.Models;
using Newtonsoft.Json.Linq;
namespace Elsa.Services
{
[Browsable(false)]
public class CompositeActivity : Activity
{
internal const string Enter = "Enter";
public virtual void Build(ICompositeActivityBuilder builder)
{
}
public bool IsScheduled
{
get => GetState<bool>();
set => SetState(value);
}
public override JObject Data
{
get
{
// When executing a composite activity's workflow, child activities might try and reference the composite activity's "input" properties.
// Out of the box, that doesn't work, since "this" points to a new instance with an empty Data object.
// Instead, we need to capture the Data object of the composite activity (the parent of the currently executing child activity) using the ambient activity execution context.
if (AmbientActivityExecutionContext.Current == null)
return base.Data;
var context = AmbientActivityExecutionContext.Current;
// Check if the currently executing activity is something other than this composite activity.
if (context.ActivityBlueprint.Type == Type)
return base.Data;
// A child activity is attempting to retrieve property data from its parent composite activity.
var parentId = context.ActivityBlueprint.Parent!.Id;
return context.WorkflowInstance.ActivityData.GetItem(parentId)!;
}
set => base.Data = value;
}
protected override async ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context)
{
if (!IsScheduled)
{
context.WorkflowInstance.Scopes.Push(new ActivityScope(Id));
IsScheduled = true;
await OnEnterAsync(context);
return Outcome(Enter);
}
IsScheduled = false;
await OnExitAsync(context);
var finishOutput = context.Input as FinishOutput;
var outcomes = new List<string> { OutcomeNames.Done };
var output = default(object?);
if (finishOutput != null)
{
outcomes.AddRange(finishOutput.Outcomes);
output = finishOutput.Output;
}
return Combine(Outcomes(outcomes), Output(output));
}
protected virtual ValueTask OnEnterAsync(ActivityExecutionContext context)
{
OnEnter(context);
return new();
}
protected virtual ValueTask OnExitAsync(ActivityExecutionContext context)
{
OnExit(context);
return new();
}
protected virtual void OnEnter(ActivityExecutionContext context)
{
}
protected virtual void OnExit(ActivityExecutionContext context)
{
}
}
}