Various API enhancements
This commit is contained in:
parent
4f3a3de208
commit
a9fbb57a09
|
|
@ -3,19 +3,17 @@ using Elsa.Models;
|
|||
|
||||
namespace Elsa.Activities.Console;
|
||||
|
||||
public class ReadLine : Activity
|
||||
public class ReadLine : Activity<string>
|
||||
{
|
||||
public ReadLine()
|
||||
{
|
||||
}
|
||||
|
||||
public ReadLine(Variable variable, Func<object?, object?>? valueConverter = default) => Output = new Output<string?>(variable, valueConverter);
|
||||
|
||||
[Output] public Output<string?>? Output { get; set; }
|
||||
public ReadLine(Variable variable, Func<object?, object?>? valueConverter = default) => Result = new Output<string?>(variable, valueConverter);
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
var text = System.Console.ReadLine();
|
||||
context.Set(Output, text);
|
||||
context.Set(Result, text);
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ public class For : Activity
|
|||
|
||||
if (loop)
|
||||
{
|
||||
context.ScheduleActivity(iterateNode, OnChildComplete);
|
||||
context.SubmitActivity(iterateNode, OnChildComplete);
|
||||
|
||||
// Update loop variable.
|
||||
CurrentValue.Set(context.ExpressionExecutionContext, currentValue);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class ForEach : Activity
|
|||
CurrentValue.Set(context, currentItem);
|
||||
|
||||
if (Body != null)
|
||||
context.ScheduleActivity(Body, OnChildCompleted);
|
||||
context.SubmitActivity(Body, OnChildCompleted);
|
||||
|
||||
// Increment index.
|
||||
context.UpdateProperty<int>(CurrentIndexProperty, x => x + 1);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@ namespace Elsa.Activities.ControlFlow;
|
|||
|
||||
public class If : Activity
|
||||
{
|
||||
public If()
|
||||
{
|
||||
}
|
||||
|
||||
public If(Input<bool> condition) => Condition = condition;
|
||||
public If(Func<ExpressionExecutionContext, bool> condition) => Condition = new Input<bool>(condition);
|
||||
public If(Func<bool> condition) => Condition = new Input<bool>(condition);
|
||||
|
||||
[Input] public Input<bool> Condition { get; set; } = new(new Literal<bool>(false));
|
||||
[Outbound] public IActivity? Then { get; set; }
|
||||
[Outbound] public IActivity? Else { get; set; }
|
||||
|
|
@ -16,7 +24,7 @@ public class If : Activity
|
|||
var nextNode = result ? Then : Else;
|
||||
|
||||
if (nextNode != null)
|
||||
context.ScheduleActivity(nextNode, OnChildCompletedAsync);
|
||||
context.SubmitActivity(nextNode, OnChildCompletedAsync);
|
||||
}
|
||||
|
||||
private ValueTask OnChildCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public class ParallelForEach<T> : Activity
|
|||
};
|
||||
|
||||
// Schedule a body of work for each item.
|
||||
context.ScheduleActivity(Body, OnChildCompleted, new[]{localVariable});
|
||||
context.SubmitActivity(Body, OnChildCompleted, new[]{localVariable});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ public class Switch : Activity
|
|||
if (matchingCase != null)
|
||||
{
|
||||
if (matchingCase.Activity != null)
|
||||
context.ScheduleActivity(matchingCase.Activity);
|
||||
context.SubmitActivity(matchingCase.Activity);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Default != null)
|
||||
context.ScheduleActivity(Default);
|
||||
context.SubmitActivity(Default);
|
||||
}
|
||||
|
||||
private async Task<SwitchCase?> FindMatchingCaseAsync(ExpressionExecutionContext context)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public class While : Activity
|
|||
var loop = context.Get(Condition);
|
||||
|
||||
if(loop)
|
||||
context.ScheduleActivity(Body, OnBodyCompleted);
|
||||
context.SubmitActivity(Body, OnBodyCompleted);
|
||||
}
|
||||
|
||||
private async ValueTask OnBodyCompleted(ActivityExecutionContext context, ActivityExecutionContext childContext)
|
||||
|
|
@ -22,6 +22,6 @@ public class While : Activity
|
|||
var loop = await context.EvaluateAsync(Condition);
|
||||
|
||||
if(loop)
|
||||
context.ScheduleActivity(Body, OnBodyCompleted);
|
||||
context.SubmitActivity(Body, OnBodyCompleted);
|
||||
}
|
||||
}
|
||||
85
src/core/Elsa.Core/Activities/Primitives/Inline.cs
Normal file
85
src/core/Elsa.Core/Activities/Primitives/Inline.cs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
using Elsa.Models;
|
||||
|
||||
namespace Elsa.Activities.Primitives;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an inline code activity that can be used to execute arbitrary .NET code from a workflow.
|
||||
/// </summary>
|
||||
public class Inline : Activity
|
||||
{
|
||||
private readonly Func<ActivityExecutionContext, ValueTask> _activity;
|
||||
|
||||
public Inline(Func<ActivityExecutionContext, ValueTask> activity) => _activity = activity;
|
||||
|
||||
public Inline(Func<ValueTask> activity) : this(_ => activity())
|
||||
{
|
||||
}
|
||||
|
||||
public Inline(Action<ActivityExecutionContext> activity) : this(c =>
|
||||
{
|
||||
activity(c);
|
||||
return new ValueTask();
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public Inline(Action activity) : this(c =>
|
||||
{
|
||||
activity();
|
||||
return new ValueTask();
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) => await _activity(context);
|
||||
|
||||
public static Inline From(Func<ActivityExecutionContext, ValueTask> activity) => new(activity);
|
||||
public static Inline From(Func<ValueTask> activity) => new(activity);
|
||||
public static Inline From(Action<ActivityExecutionContext> activity) => new(activity);
|
||||
public static Inline From(Action activity) => new(activity);
|
||||
|
||||
public static Inline<T> From<T>(Func<ActivityExecutionContext, ValueTask<T>> activity) => new(activity);
|
||||
public static Inline<T> From<T>(Func<ValueTask<T>> activity) => new(activity);
|
||||
public static Inline<T> From<T>(Func<ActivityExecutionContext, T> activity) => new(activity);
|
||||
public static Inline<T> From<T>(Func<T> activity) => new(activity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an inline code activity that can be used to execute arbitrary .NET code from a workflow and return a value.
|
||||
/// </summary>
|
||||
public class Inline<T> : Activity<T>
|
||||
{
|
||||
private readonly Func<ActivityExecutionContext, ValueTask<T>> _activity;
|
||||
|
||||
public Inline(Func<ActivityExecutionContext, ValueTask<T>> activity, RegisterLocationReference? output = default)
|
||||
{
|
||||
_activity = activity;
|
||||
if (output != null) Result = new Output(output);
|
||||
}
|
||||
|
||||
public Inline(Func<ValueTask<T>> activity, RegisterLocationReference? output = default) : this(_ => activity(), output)
|
||||
{
|
||||
}
|
||||
|
||||
public Inline(Func<ActivityExecutionContext, T> activity, RegisterLocationReference? output = default) : this(c =>
|
||||
{
|
||||
var result = activity(c);
|
||||
return new ValueTask<T>(result);
|
||||
}, output)
|
||||
{
|
||||
}
|
||||
|
||||
public Inline(Func<T> activity, RegisterLocationReference? output = default) : this(c =>
|
||||
{
|
||||
var result = activity();
|
||||
return new ValueTask<T>(result);
|
||||
}, output)
|
||||
{
|
||||
}
|
||||
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
var result = await _activity(context);
|
||||
context.Set(Result, result);
|
||||
}
|
||||
}
|
||||
62
src/core/Elsa.Core/Activities/Workflows/Composite.cs
Normal file
62
src/core/Elsa.Core/Activities/Workflows/Composite.cs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
using Elsa.Activities.Primitives;
|
||||
using Elsa.Attributes;
|
||||
using Elsa.Contracts;
|
||||
using Elsa.Models;
|
||||
|
||||
namespace Elsa.Activities.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a composite activity that has a single <see cref="Root"/> activity.
|
||||
/// </summary>
|
||||
public class Composite : Activity
|
||||
{
|
||||
/// <summary>
|
||||
/// The activity to schedule when this activity executes.
|
||||
/// </summary>
|
||||
[Outbound]
|
||||
public IActivity Root { get; protected set; } = new Sequence();
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
context.SubmitActivity(Root, OnCompletedAsync);
|
||||
}
|
||||
|
||||
protected virtual ValueTask OnCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext) => ValueTask.CompletedTask;
|
||||
|
||||
protected static Inline From(Func<ActivityExecutionContext, ValueTask> activity) => new(activity);
|
||||
protected static Inline From(Func<ValueTask> activity) => new(activity);
|
||||
protected static Inline From(Action<ActivityExecutionContext> activity) => new(activity);
|
||||
protected static Inline From(Action activity) => new(activity);
|
||||
protected static Inline<TResult> From<TResult>(Func<ActivityExecutionContext, ValueTask<TResult>> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
protected static Inline<TResult> From<TResult>(Func<ValueTask<TResult>> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
protected static Inline<TResult> From<TResult>(Func<ActivityExecutionContext, TResult> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
protected static Inline<TResult> From<TResult>(Func<TResult> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a composite activity that has a single <see cref="Root"/> activity and returns a result.
|
||||
/// </summary>
|
||||
public class Composite<T> : Activity<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The activity to schedule when this activity executes.
|
||||
/// </summary>
|
||||
[Outbound]
|
||||
public IActivity Root { get; protected set; } = new Sequence();
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
context.SubmitActivity(Root, OnCompletedAsync);
|
||||
}
|
||||
|
||||
protected virtual ValueTask OnCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext) => ValueTask.CompletedTask;
|
||||
|
||||
protected static Inline From(Func<ActivityExecutionContext, ValueTask> activity) => new(activity);
|
||||
protected static Inline From(Func<ValueTask> activity) => new(activity);
|
||||
protected static Inline From(Action<ActivityExecutionContext> activity) => new(activity);
|
||||
protected static Inline From(Action activity) => new(activity);
|
||||
protected static Inline<TResult> From<TResult>(Func<ActivityExecutionContext, ValueTask<TResult>> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
protected static Inline<TResult> From<TResult>(Func<ValueTask<TResult>> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
protected static Inline<TResult> From<TResult>(Func<ActivityExecutionContext, TResult> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
protected static Inline<TResult> From<TResult>(Func<TResult> activity, RegisterLocationReference? output = default) => new(activity, output);
|
||||
}
|
||||
|
|
@ -12,6 +12,13 @@ public abstract class Container : Activity, IContainer
|
|||
}
|
||||
|
||||
protected Container(params IActivity[] activities) => Activities = activities;
|
||||
|
||||
protected Container(ICollection<Variable> variables, params IActivity[] activities)
|
||||
{
|
||||
Variables = variables;
|
||||
Activities = activities;
|
||||
}
|
||||
|
||||
[Outbound] public ICollection<IActivity> Activities { get; set; } = new List<IActivity>();
|
||||
public ICollection<Variable> Variables { get; set; } = new Collection<Variable>();
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class Flowchart : Container
|
|||
if (Start == null!)
|
||||
return;
|
||||
|
||||
context.ScheduleActivity(Start, OnChildCompleted);
|
||||
context.SubmitActivity(Start, OnChildCompleted);
|
||||
}
|
||||
|
||||
private ValueTask OnChildCompleted(ActivityExecutionContext context, ActivityExecutionContext childContext)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ public class Sequence : Container
|
|||
public Sequence(params IActivity[] activities) : base(activities)
|
||||
{
|
||||
}
|
||||
|
||||
public Sequence(ICollection<Variable> variables, params IActivity[] activities) : base(variables, activities)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ScheduleChildren(ActivityExecutionContext context)
|
||||
{
|
||||
|
|
@ -31,7 +35,7 @@ public class Sequence : Container
|
|||
return;
|
||||
|
||||
var nextActivity = childActivities.ElementAt(currentIndex);
|
||||
context.ScheduleActivity(nextActivity, OnChildCompleted);
|
||||
context.SubmitActivity(nextActivity, OnChildCompleted);
|
||||
context.UpdateProperty<int>(CurrentIndexProperty, x => x + 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,4 +21,7 @@ public static class ActivityExecutionContextExtensions
|
|||
workflowExecutionContext.ExecutionLog.Add(logEntry);
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
public static Variable SetVariable(this ActivityExecutionContext context, string name, object? value) => context.WorkflowExecutionContext.SetVariable(name, value);
|
||||
public static T? GetVariable<T>(this ActivityExecutionContext context, string name) => context.WorkflowExecutionContext.GetVariable<T?>(name);
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ public class ActivityExecutionContext
|
|||
/// </summary>
|
||||
public IDictionary<string, object?> JournalData { get; private set; } = new Dictionary<string, object?>();
|
||||
|
||||
public void ScheduleActivity(IActivity? activity, ActivityCompletionCallback? completionCallback = default, IEnumerable<RegisterLocationReference>? locationReferences = default, object? tag = default)
|
||||
public void SubmitActivity(IActivity? activity, ActivityCompletionCallback? completionCallback = default, IEnumerable<RegisterLocationReference>? locationReferences = default, object? tag = default)
|
||||
{
|
||||
if (activity == null)
|
||||
return;
|
||||
|
|
@ -76,7 +76,7 @@ public class ActivityExecutionContext
|
|||
WorkflowExecutionContext.Schedule(activity, this, completionCallback, locationReferences, tag);
|
||||
}
|
||||
|
||||
public void ScheduleActivity(IActivity? activity, ActivityExecutionContext owner, ActivityCompletionCallback? completionCallback = default, IEnumerable<RegisterLocationReference>? locationReferences = default, object? tag = default)
|
||||
public void SubmitActivity(IActivity? activity, ActivityExecutionContext owner, ActivityCompletionCallback? completionCallback = default, IEnumerable<RegisterLocationReference>? locationReferences = default, object? tag = default)
|
||||
{
|
||||
if (activity == null)
|
||||
return;
|
||||
|
|
@ -89,7 +89,7 @@ public class ActivityExecutionContext
|
|||
public void ScheduleActivities(IEnumerable<IActivity?> activities, ActivityCompletionCallback? completionCallback = default)
|
||||
{
|
||||
foreach (var activity in activities)
|
||||
ScheduleActivity(activity, completionCallback);
|
||||
SubmitActivity(activity, completionCallback);
|
||||
}
|
||||
|
||||
public void CreateBookmarks(IEnumerable<object> bookmarkData, ExecuteActivityDelegate? callback = default)
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
using Elsa.Activities.Workflows;
|
||||
using Elsa.Attributes;
|
||||
using Elsa.Contracts;
|
||||
|
||||
namespace Elsa.Models;
|
||||
|
||||
public abstract class Composite : Activity
|
||||
{
|
||||
[Outbound] public IActivity Root { get; protected set; } = new Sequence();
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
context.ScheduleActivity(Root, OnCompletedAsync);
|
||||
}
|
||||
|
||||
protected virtual ValueTask OnCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext) => ValueTask.CompletedTask;
|
||||
}
|
||||
|
|
@ -5,8 +5,17 @@ using Elsa.Models;
|
|||
|
||||
namespace Elsa.Modules.Scheduling.Activities;
|
||||
|
||||
[Activity("Scheduling", "Delays execution for the specified amount of time.")]
|
||||
public class Delay : Activity
|
||||
{
|
||||
public Delay()
|
||||
{
|
||||
}
|
||||
|
||||
public Delay(Input<TimeSpan> timeSpan) => TimeSpan = timeSpan;
|
||||
public Delay(TimeSpan timeSpan) => TimeSpan = new Input<TimeSpan>(timeSpan);
|
||||
public Delay(Variable<TimeSpan> timeSpan) => TimeSpan = new Input<TimeSpan>(timeSpan);
|
||||
|
||||
[Input] public Input<TimeSpan> TimeSpan { get; set; } = default!;
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public static class VariablesWorkflow
|
|||
new WriteLine(context => greeting.Get(context)),
|
||||
new ReadLine
|
||||
{
|
||||
Output = new Output<string?>(name)
|
||||
Result = new Output<string?>(name)
|
||||
},
|
||||
new WriteLine(new DelegateReference(context => $"Nice to meet you, {name.Get(context)}!")),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ typeSystem.Register<HttpEndpoint>();
|
|||
typeSystem.Register<Timer>();
|
||||
|
||||
functionActivityRegistry.RegisterFunction("print", nameof(WriteLine), new[] { nameof(WriteLine.Text) });
|
||||
functionActivityRegistry.RegisterFunction("read", nameof(ReadLine), new[] { nameof(ReadLine.Output) });
|
||||
functionActivityRegistry.RegisterFunction("read", nameof(ReadLine), new[] { nameof(ReadLine.Result) });
|
||||
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resource = assembly.GetManifestResourceStream("Elsa.Samples.Console2.Sample1.elsa");
|
||||
|
|
|
|||
Loading…
Reference in a new issue