< Summary

Information
Class: Elsa.Workflows.Activities.ForEach<T>
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/ForEachT.cs
Line coverage
87%
Covered lines: 35
Uncovered lines: 5
Coverable lines: 40
Total lines: 113
Line coverage: 87.5%
Branch coverage
83%
Covered branches: 5
Total branches: 6
Branch coverage: 83.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
.ctor(...)100%210%
.ctor(...)100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
get_Items()100%11100%
get_Body()100%11100%
get_CurrentValue()100%11100%
ExecuteAsync()100%11100%
HandleIteration()87.5%8895%
OnChildCompleted()100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/ForEachT.cs

#LineLine coverage
 1using System.Runtime.CompilerServices;
 2using Elsa.Expressions.Models;
 3using Elsa.Extensions;
 4using Elsa.Workflows.Attributes;
 5using Elsa.Workflows.Behaviors;
 6using Elsa.Workflows.Memory;
 7using Elsa.Workflows.Models;
 8
 9namespace Elsa.Workflows.Activities;
 10
 11/// <summary>
 12/// A strongly-typed for-each construct where <typeparamref name="T"/> is the item type.
 13/// </summary>
 14/// <typeparam name="T">The type of items in the collection to iterate over.</typeparam>
 15public class ForEach<T> : Activity
 16{
 17    private const string CurrentIndexProperty = "CurrentIndex";
 18
 19    /// <inheritdoc />
 020    public ForEach(Func<ExpressionExecutionContext, ICollection<T>> @delegate, [CallerFilePath] string? source = null, [
 21    {
 022    }
 23
 24    /// <inheritdoc />
 025    public ForEach(Func<ICollection<T>> @delegate, [CallerFilePath] string? source = null, [CallerLineNumber] int? line 
 26    {
 027    }
 28
 29    /// <inheritdoc />
 2530    public ForEach(ICollection<T> items, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : 
 31    {
 2532    }
 33
 34    /// <inheritdoc />
 2835    public ForEach(Input<ICollection<T>> items, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = n
 36    {
 2837        Items = items;
 2838    }
 39
 40    /// <inheritdoc />
 2841    public ForEach([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null)
 42    {
 2843        Behaviors.Add<BreakBehavior>(this);
 2844    }
 45
 46    /// <summary>
 47    /// The set of values to iterate.
 48    /// </summary>
 49    [Input(Description = "The set of values to iterate.")]
 14850    public Input<ICollection<T>> Items { get; set; } = new(Array.Empty<T>());
 51
 52    /// <summary>
 53    /// The activity to execute for each iteration.
 54    /// </summary>
 55    [Port]
 13956    public IActivity? Body { get; set; }
 57
 58    /// <summary>
 59    /// The current value being iterated will be assigned to the specified <see cref="MemoryBlockReference"/>.
 60    /// </summary>
 61    [Output(Description = "Assign the current value to the specified variable.")]
 7262    public Output<T>? CurrentValue { get; set; }
 63
 64    /// <inheritdoc />
 65    protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
 66    {
 67        // Execute first iteration.
 1168        await HandleIteration(context);
 1069    }
 70
 71    private async Task HandleIteration(ActivityExecutionContext context)
 72    {
 3573        var isBreaking = context.GetIsBreaking();
 74
 3575        if (isBreaking)
 76        {
 177            await context.CompleteActivityAsync();
 178            return;
 79        }
 80
 3481        var currentIndex = context.GetProperty<int>(CurrentIndexProperty);
 3482        var items = context.Get(Items)!.ToList();
 83
 3384        if (currentIndex >= items.Count)
 85        {
 886            await context.CompleteActivityAsync();
 887            return;
 88        }
 89
 2590        var currentValue = items[currentIndex];
 2591        context.Set(CurrentValue, currentValue);
 92
 2593        if (Body != null)
 94        {
 2595            var variables = new[]
 2596            {
 2597                new Variable("CurrentIndex", currentIndex),
 2598                new Variable("CurrentValue", currentValue)
 2599            };
 25100            await context.ScheduleActivityAsync(Body, OnChildCompleted, variables: variables);
 101        }
 102        else
 0103            await context.CompleteActivityAsync();
 104
 105        // Increment index.
 50106        context.UpdateProperty<int>(CurrentIndexProperty, x => x + 1);
 34107    }
 108
 109    private async ValueTask OnChildCompleted(ActivityCompletedContext context)
 110    {
 24111        await HandleIteration(context.TargetContext);
 24112    }
 113}