< Summary

Line coverage
70%
Covered lines: 163
Uncovered lines: 68
Coverable lines: 231
Total lines: 649
Line coverage: 70.5%
Branch coverage
65%
Covered branches: 68
Total branches: 104
Branch coverage: 65.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: TryGetWorkflowInput(...)100%22100%
File 1: GetWorkflowInput(...)100%11100%
File 1: GetWorkflowInput(...)100%11100%
File 1: SetResult(...)100%22100%
File 1: IsTriggerOfWorkflow(...)100%11100%
File 1: CreateVariable(...)100%11100%
File 1: SetVariable(...)100%11100%
File 1: SetDynamicVariable(...)0%4260%
File 1: GetVariable(...)100%11100%
File 1: GetVariableValues(...)100%11100%
File 1: GetActivitiesWithOutputs()66.66%6688.88%
File 1: GetActivitiesWithOutputs()100%88100%
File 1: FindActivityByIdOrName(...)0%7280%
File 1: GetOutcomeName(...)100%44100%
File 1: SendSignalAsync()100%66100%
File 1: ScheduleOutcomesAsync()0%2040%
File 1: CancelActivityAsync()33.33%22623.07%
File 1: Fault(...)100%22100%
File 1: RecoverFromFault(...)50%2283.33%
File 1: FindParentWithVariableContainer(...)100%11100%
File 1: FindParent(...)75%4483.33%
File 1: GetAncestors()100%22100%
File 1: GetDescendents()0%2040%
File 1: GetActiveChildren(...)100%210%
File 1: GetChildren(...)100%210%
File 1: GetDescendants()25%7442.85%
File 1: SetExtensionsMetadata(...)100%22100%
File 1: GetExtensionsMetadata(...)100%22100%
File 1: GetActivityOutput(...)50%4475%
File 1: GetHasEvaluatedProperties(...)100%11100%
File 1: SetHasEvaluatedProperties(...)100%11100%
File 2: EvaluateInputPropertiesAsync()100%22100%
File 2: EvaluateInputPropertyAsync()100%11100%
File 2: EvaluateInputPropertyAsync()50%4487.5%
File 2: EvaluateAsync()100%210%
File 2: EvaluateInputPropertyAsync()100%11100%
File 2: EvaluateInputPropertyCoreAsync()94.44%181896.87%
File 2: StoreInputValueAsync(...)100%22100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Extensions/ActivityExecutionContextExtensions.cs

#LineLine coverage
 1using System.Linq.Expressions;
 2using System.Reflection;
 3using System.Text.Json;
 4using Elsa.Common;
 5using Elsa.Expressions.Contracts;
 6using Elsa.Expressions.Helpers;
 7using Elsa.Expressions.Models;
 8using Elsa.Mediator.Contracts;
 9using Elsa.Workflows;
 10using Elsa.Workflows.Attributes;
 11using Elsa.Workflows.Memory;
 12using Elsa.Workflows.Models;
 13using Elsa.Workflows.Notifications;
 14using Elsa.Workflows.Signals;
 15using Elsa.Workflows.State;
 16using JetBrains.Annotations;
 17using Microsoft.Extensions.Logging;
 18
 19// ReSharper disable once CheckNamespace
 20namespace Elsa.Extensions;
 21
 22/// <summary>
 23/// Provides extension methods for <see cref="ActivityExecutionContext"/>.
 24/// </summary>
 25[PublicAPI]
 26public static partial class ActivityExecutionContextExtensions
 27{
 28    private const string ExtensionsMetadataKey = "Extensions";
 29
 30    /// <param name="context">The <see cref="ActivityExecutionContext"/></param>
 31    extension(ActivityExecutionContext context)
 32    {
 33        /// <summary>
 34        /// Attempts to get a value from the input provided via <see cref="WorkflowExecutionContext"/>. If a value was f
 35        /// </summary>
 36        public bool TryGetWorkflowInput<T>(string key, out T value, JsonSerializerOptions? serializerOptions = null)
 37        {
 1138            var wellKnownTypeRegistry = context.GetRequiredService<IWellKnownTypeRegistry>();
 39
 1140            if (context.WorkflowInput.TryGetValue(key, out var v))
 41            {
 1042                value = v.ConvertTo<T>(new(serializerOptions, wellKnownTypeRegistry))!;
 1043                return true;
 44            }
 45
 146            value = default!;
 147            return false;
 48        }
 49
 50        /// <summary>
 51        /// Gets a value from the input provided via <see cref="WorkflowExecutionContext"/>. If a value was found, an at
 52        /// </summary>
 153        public T GetWorkflowInput<T>(JsonSerializerOptions? serializerOptions = null) => context.GetWorkflowInput<T>(typ
 54
 55        /// <summary>
 56        /// Gets a value from the input provided via <see cref="WorkflowExecutionContext"/>. If a value was found, an at
 57        /// </summary>
 58        public T GetWorkflowInput<T>(string key, JsonSerializerOptions? serializerOptions = null)
 59        {
 21760            var wellKnownTypeRegistry = context.GetRequiredService<IWellKnownTypeRegistry>();
 21761            return context.WorkflowInput[key].ConvertTo<T>(new(serializerOptions, wellKnownTypeRegistry))!;
 62        }
 63
 64        /// <summary>
 65        /// Sets the Result property of the specified activity.
 66        /// </summary>
 67        /// being extended.
 68        /// <param name="value">The value to set.</param>
 69        /// <exception cref="Exception">Thrown when the specified activity does not implement <see cref="IActivityWithRe
 70        public void SetResult(object? value)
 71        {
 1972            var activity = context.Activity as IActivityWithResult ?? throw new($"Cannot set result on activity {context
 1873            context.Set(activity.Result, value, "Result");
 1874        }
 75
 76        /// <summary>
 77        /// Returns true if this activity is triggered for the first time and not being resumed.
 78        /// </summary>
 25379        public bool IsTriggerOfWorkflow() => context.WorkflowExecutionContext.TriggerActivityId == context.Activity.Id;
 80
 81        /// <summary>
 82        /// Creates a workflow variable by name and optionally sets the value.
 83        /// </summary>
 84        /// <param name="name">The name of the variable.</param>
 85        /// <param name="value">The value of the variable.</param>
 86        /// <param name="storageDriverType">The type of storage driver to use for the variable.</param>
 87        /// <param name="configure">A callback to configure the memory block.</param>
 88        /// <returns>The created <see cref="Variable"/>.</returns>
 89        public Variable CreateVariable(string name, object? value, Type? storageDriverType = null, Action<MemoryBlock>? 
 90        {
 191            return context.ExpressionExecutionContext.CreateVariable(name, value, storageDriverType, configure);
 92        }
 93
 94        /// <summary>
 95        /// Sets a workflow variable by name.
 96        /// </summary>
 97        /// <param name="name">The name of the variable.</param>
 98        /// <param name="value">The value of the variable.</param>
 99        /// <param name="configure">A callback to configure the memory block.</param>
 100        /// <returns>The created <see cref="Variable"/>.</returns>
 101        public Variable SetVariable(string name, object? value, Action<MemoryBlock>? configure = null) =>
 10102            context.ExpressionExecutionContext.SetVariable(name, value, configure);
 103
 104        public Variable SetDynamicVariable<T>(string name, T value, Action<MemoryBlock>? configure = null)
 105        {
 106            // Check if a predefined variable already exists.
 0107            var predefinedVariable = context.ExpressionExecutionContext.GetVariable(name);
 108
 0109            if (predefinedVariable != null)
 110            {
 0111                context.SetVariable(name, value);
 0112                return predefinedVariable;
 113            }
 114
 115            // No predefined variable exists, so we will add a dynamic variable to the current container in scope.
 0116            var container = context.FindParentWithVariableContainer();
 117
 0118            if (container == null)
 0119                throw new("No parent variable container found");
 120
 0121            var existingVariable = container.DynamicVariables.FirstOrDefault(x => x.Name == name);
 122
 0123            if (existingVariable == null)
 0124                container.DynamicVariables.Add(new Variable<T>(name, value));
 125
 0126            return context.SetVariable(name, value);
 127        }
 128
 129        /// <summary>
 130        /// Gets a workflow variable by name.
 131        /// </summary>
 132        /// <param name="name">The name of the variable.</param>
 133        /// <typeparam name="T">The type of the variable.</typeparam>
 134        /// <returns>The variable if found, otherwise null.</returns>
 9135        public T? GetVariable<T>(string name) => context.ExpressionExecutionContext.GetVariable<T?>(name);
 136
 137        /// <summary>
 138        /// Returns a dictionary of variable keys and their values across scopes.
 139        /// </summary>
 1140        public IDictionary<string, object> GetVariableValues() => context.ExpressionExecutionContext.ReadAndFlattenMemor
 141
 142        /// <summary>
 143        /// Returns a set of tuples containing the activity and its descriptor for all activities with outputs.
 144        /// </summary>
 145        public async IAsyncEnumerable<(IActivity Activity, ActivityDescriptor ActivityDescriptor)> GetActivitiesWithOutp
 146        {
 147            // Get current container.
 9148            var currentContainerNode = context.FindParentWithVariableContainer()?.ActivityNode;
 149
 9150            if (currentContainerNode == null)
 0151                yield break;
 152
 153            // Get all nodes in the current container
 9154            var workflowExecutionContext = context.WorkflowExecutionContext;
 33155            var containedNodes = workflowExecutionContext.Nodes.Where(x => x.Parents.Contains(currentContainerNode)).Dis
 156
 157            // Select activities with outputs.
 9158            var activityRegistry = workflowExecutionContext.GetRequiredService<IActivityRegistryLookupService>();
 9159            var activitiesWithOutputs = containedNodes.GetActivitiesWithOutputs(activityRegistry);
 160
 28161            await foreach (var (activity, activityDescriptor) in activitiesWithOutputs)
 5162                yield return (activity, activityDescriptor);
 9163        }
 164    }
 165
 166    /// <summary>
 167    /// Returns a set of tuples containing the activity and its descriptor for all activities with outputs.
 168    /// </summary>
 169    public static async IAsyncEnumerable<(IActivity activity, ActivityDescriptor activityDescriptor)> GetActivitiesWithO
 170    {
 36171        foreach (var node in nodes)
 172        {
 9173            var activity = node.Activity;
 9174            var activityDescriptor = await activityRegistryLookup.FindAsync(activity.Type, activity.Version);
 9175            if (activityDescriptor != null && activityDescriptor.Outputs.Any())
 5176                yield return (activity, activityDescriptor);
 9177        }
 9178    }
 179
 180    /// <param name="activityExecutionContext">The <see cref="ActivityExecutionContext"/> being extended.</param>
 181    extension(ActivityExecutionContext activityExecutionContext)
 182    {
 183        /// <summary>
 184        /// Returns the activity with the specified ID or name.
 185        /// </summary>
 186        public IActivity? FindActivityByIdOrName(string idOrName)
 187        {
 188            // Get current container.
 0189            var currentContainerNode = activityExecutionContext.FindParentWithVariableContainer()?.ActivityNode;
 190
 0191            if (currentContainerNode == null)
 0192                return null;
 193
 194            // Get all nodes in the current container
 0195            var workflowExecutionContext = activityExecutionContext.WorkflowExecutionContext;
 0196            var containedNodes = workflowExecutionContext.Nodes.Where(x => x.Parents.Contains(currentContainerNode)).Dis
 0197            var node = containedNodes.FirstOrDefault(x => x.Activity.Name == idOrName || x.Activity.Id == idOrName);
 0198            return node?.Activity;
 199        }
 200
 201        /// <summary>
 202        /// Returns the outcome name for the specified port property name.
 203        /// </summary>
 204        /// <param name="portPropertyName">The name of the port property.</param>
 205        /// <returns>The outcome name.</returns>
 206        public string GetOutcomeName(string portPropertyName)
 207        {
 2208            var owner = activityExecutionContext.Activity;
 28209            var ports = owner.GetType().GetProperties().Where(x => typeof(IActivity).IsAssignableFrom(x.PropertyType)).T
 210
 2211            var portQuery =
 2212                from p in ports
 2213                where p.Name == portPropertyName
 2214                select p;
 215
 2216            var portProperty = portQuery.First();
 2217            return portProperty.GetCustomAttribute<PortAttribute>()?.Name ?? portProperty.Name;
 218        }
 219
 220        /// <summary>
 221        /// Send a signal up the current hierarchy of ancestors.
 222        /// </summary>
 223        public async ValueTask SendSignalAsync(object signal)
 224        {
 3130225            var receivingContexts = new[]
 3130226            {
 3130227                activityExecutionContext
 3130228            }.Concat(activityExecutionContext.GetAncestors()).ToList();
 3130229            var logger = activityExecutionContext.GetRequiredService<ILogger<ActivityExecutionContext>>();
 3130230            var signalType = signal.GetType();
 3130231            var signalTypeName = signalType.Name;
 232
 233            // Let all ancestors receive the signal.
 30621234            foreach (var ancestorContext in receivingContexts)
 235            {
 12182236                var signalContext = new SignalContext(ancestorContext, activityExecutionContext, activityExecutionContex
 237
 12182238                if (ancestorContext.Activity is not ISignalHandler handler)
 239                    continue;
 240
 12182241                logger.LogDebug("Receiving signal {SignalType} on activity {ActivityId} of type {ActivityType}", signalT
 12182242                await handler.ReceiveSignalAsync(signal, signalContext);
 243
 12182244                if (signalContext.StopPropagationRequested)
 245                {
 3246                    logger.LogDebug("Propagation of signal {SignalType} on activity {ActivityId} of type {ActivityType} 
 3247                    return;
 248                }
 12179249            }
 3130250        }
 251
 252        /// <summary>
 253        /// Complete the current activity. This should only be called by activities that explicitly suppress automatic-c
 254        /// </summary>
 255        public async ValueTask ScheduleOutcomesAsync(params string[] outcomes)
 256        {
 257            // Record the outcomes, if any.
 0258            activityExecutionContext.JournalData["Outcomes"] = outcomes;
 259
 260            // Record the output, if any.
 0261            var activity = activityExecutionContext.Activity;
 0262            var expressionExecutionContext = activityExecutionContext.ExpressionExecutionContext;
 0263            var activityDescriptor = activityExecutionContext.ActivityDescriptor;
 0264            var outputDescriptors = activityDescriptor.Outputs;
 0265            var outputs = outputDescriptors.ToDictionary(x => x.Name, x => activity.GetOutput(expressionExecutionContext
 0266            var serializer = activityExecutionContext.GetRequiredService<ISafeSerializer>();
 267
 0268            foreach (var output in outputs)
 269            {
 0270                var outputName = output.Key;
 0271                var outputValue = output.Value;
 272
 0273                if (outputValue == null!)
 274                    continue;
 275
 0276                var serializedOutputValue = serializer.Serialize(outputValue);
 0277                activityExecutionContext.JournalData[outputName] = serializedOutputValue;
 278            }
 279
 280            // Send a signal.
 0281            await activityExecutionContext.SendSignalAsync(new ScheduleActivityOutcomes(outcomes));
 0282        }
 283
 284        /// <summary>
 285        /// Cancel the activity. For blocking activities, it means their bookmarks will be removed. For job activities, 
 286        /// </summary>
 287        public async Task CancelActivityAsync()
 288        {
 289            // If the activity is not running, do nothing.
 93290            if (activityExecutionContext.Status != ActivityStatus.Running && activityExecutionContext.Status != Activity
 93291                return;
 292
 293            // Select all child contexts.
 0294            var childContexts = activityExecutionContext.Children.ToList();
 295
 0296            foreach (var childContext in childContexts)
 0297                await CancelActivityAsync(childContext);
 298
 0299            var publisher = activityExecutionContext.GetRequiredService<INotificationSender>();
 0300            activityExecutionContext.TransitionTo(ActivityStatus.Canceled);
 0301            activityExecutionContext.ClearBookmarks();
 0302            activityExecutionContext.ClearCompletionCallbacks();
 0303            activityExecutionContext.WorkflowExecutionContext.Bookmarks.RemoveWhere(x => x.ActivityNodeId == activityExe
 304
 305            // Add an execution log entry.
 0306            activityExecutionContext.AddExecutionLogEntry("Canceled");
 307
 0308            await activityExecutionContext.SendSignalAsync(new CancelSignal());
 0309            await publisher.SendAsync(new ActivityCancelled(activityExecutionContext));
 93310        }
 311
 312        /// <summary>
 313        /// Marks the current activity as faulted, records an exception, and transitions its status to <see cref="Activi
 314        /// An incident is logged, and the fault count for the activity and its ancestor activities is incremented.
 315        /// </summary>
 316        /// <param name="e">The exception to be recorded as the cause of the fault.</param>
 317        public void Fault(Exception e)
 318        {
 15319            activityExecutionContext.Exception = e;
 15320            activityExecutionContext.TransitionTo(ActivityStatus.Faulted);
 15321            var activity = activityExecutionContext.Activity;
 15322            var exceptionState = ExceptionState.FromException(e);
 15323            var systemClock = activityExecutionContext.GetRequiredService<ISystemClock>();
 15324            var now = systemClock.UtcNow;
 15325            var incident = new ActivityIncident(activity.Id, activity.NodeId, activity.Type, e.Message, exceptionState, 
 15326            activityExecutionContext.WorkflowExecutionContext.Incidents.Add(incident);
 15327            activityExecutionContext.AggregateFaultCount++;
 328
 15329            var ancestors = activityExecutionContext.GetAncestors();
 330
 82331            foreach (var ancestor in ancestors)
 26332                ancestor.AggregateFaultCount++;
 15333        }
 334
 335        /// <summary>
 336        /// Recovers the current activity from a faulted state by resetting fault counts and transitioning the activity 
 337        /// </summary>
 338        public void RecoverFromFault()
 339        {
 1340            activityExecutionContext.AggregateFaultCount = 0;
 341
 1342            var ancestors = activityExecutionContext.GetAncestors();
 343
 2344            foreach (var ancestor in ancestors)
 0345                ancestor.AggregateFaultCount--;
 346
 1347            activityExecutionContext.TransitionTo(ActivityStatus.Running);
 1348        }
 349
 350        /// <summary>
 351        /// Returns the first context that is associated with a <see cref="IVariableContainer"/>.
 352        /// </summary>
 353        public ActivityExecutionContext? FindParentWithVariableContainer()
 354        {
 53355            return activityExecutionContext.FindParent(x => x.Activity is IVariableContainer);
 356        }
 357
 358        /// <summary>
 359        /// Returns the first context in the hierarchy that matches the specified predicate.
 360        /// </summary>
 361        /// <param name="predicate">The predicate to match.</param>
 362        /// <returns>The first context that matches the predicate or <c>null</c> if no match was found.</returns>
 363        public ActivityExecutionContext? FindParent(Func<ActivityExecutionContext, bool> predicate)
 364        {
 23365            var currentContext = activityExecutionContext;
 366
 33367            while (currentContext != null)
 368            {
 32369                if (predicate(currentContext))
 22370                    return currentContext;
 371
 10372                currentContext = currentContext.ParentActivityExecutionContext;
 373            }
 374
 1375            return null;
 376        }
 377
 378        /// <summary>
 379        /// Returns a flattened list of the current context's ancestors.
 380        /// </summary>
 381        public IEnumerable<ActivityExecutionContext> GetAncestors()
 382        {
 9281383            var current = activityExecutionContext.ParentActivityExecutionContext;
 384
 29977385            while (current != null)
 386            {
 23380387                yield return current;
 20696388                current = current.ParentActivityExecutionContext;
 389            }
 6597390        }
 391
 392        /// <summary>
 393        /// Returns a flattened list of the current context's descendants.
 394        /// </summary>
 395        public IEnumerable<ActivityExecutionContext> GetDescendents()
 396        {
 0397            var children = activityExecutionContext.Children.ToList();
 398
 0399            foreach (var child in children)
 400            {
 0401                yield return child;
 402
 0403                foreach (var descendent in GetDescendents(child))
 0404                    yield return descendent;
 0405            }
 0406        }
 407
 408        /// <summary>
 409        /// Returns a flattened list of the current context's immediate active children.
 410        /// </summary>
 411        public IEnumerable<ActivityExecutionContext> GetActiveChildren()
 412        {
 0413            return activityExecutionContext.Children;
 414        }
 415
 416        /// <summary>
 417        /// Returns a flattened list of the current context's immediate children.
 418        /// </summary>
 419        public IEnumerable<ActivityExecutionContext> GetChildren()
 420        {
 0421            return activityExecutionContext.Children;
 422        }
 423
 424        /// <summary>
 425        /// Returns a flattened list of the current context's descendants.
 426        /// </summary>
 427        public IEnumerable<ActivityExecutionContext> GetDescendants()
 428        {
 1429            var children = activityExecutionContext.Children.ToList();
 430
 2431            foreach (var child in children)
 432            {
 0433                yield return child;
 434
 0435                foreach (var descendant in child.GetDescendants())
 0436                    yield return descendant;
 0437            }
 1438        }
 439
 440        /// <summary>
 441        /// Sets extension data in the metadata. Represents specific data that is exposed generically for an activity.
 442        /// </summary>
 443        public void SetExtensionsMetadata(string key, object? value)
 444        {
 4445            var extensionsDictionary = activityExecutionContext.GetExtensionsMetadata() ?? new Dictionary<string, object
 446
 4447            extensionsDictionary[key] = value;
 448
 4449            activityExecutionContext.Metadata[ExtensionsMetadataKey] = extensionsDictionary;
 4450        }
 451
 452        /// <summary>
 453        /// Retrieves the extension data from the metadata. Represents specific data that is exposed generically for an 
 454        /// </summary>
 455        public Dictionary<string, object?>? GetExtensionsMetadata()
 456        {
 7457            return activityExecutionContext.Metadata.TryGetValue(ExtensionsMetadataKey, out var value) ? value as Dictio
 458        }
 459
 460        /// <summary>
 461        /// Gets the output of an activity even when the context is not the same as the activity's context.
 462        /// This is useful when you want to get the output of a previously executed activity.
 463        /// </summary>
 464        /// <param name="property"></param>
 465        /// <typeparam name="TProp"></typeparam>
 466        /// <returns></returns>
 467        public object? GetActivityOutput<TProp>(Expression<Func<TProp>> property)
 468        {
 71469            if (property.Body is not MemberExpression memberExpr)
 470            {
 0471                return null;
 472            }
 473
 71474            var propertyName = memberExpr.Member.Name;
 475
 71476            var value = activityExecutionContext.Get(propertyName);
 477
 71478            if (value != null)
 0479                return value;
 480
 71481            var registry = activityExecutionContext.WorkflowExecutionContext.GetActivityOutputRegister();
 482
 71483            return registry.FindOutputByActivityInstanceId(activityExecutionContext.Id, propertyName);
 484        }
 485
 8393486        public bool GetHasEvaluatedProperties() => activityExecutionContext.TransientProperties.TryGetValue<bool>("HasEv
 3477487        public void SetHasEvaluatedProperties() => activityExecutionContext.TransientProperties["HasEvaluatedProperties"
 488    }
 489}

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Extensions/ActivityExecutionContextExtensions.InputEvaluation.cs

#LineLine coverage
 1using System.Linq.Expressions;
 2using Elsa.Expressions.Contracts;
 3using Elsa.Expressions.Helpers;
 4using Elsa.Expressions.Models;
 5using Elsa.Workflows;
 6using Elsa.Workflows.Exceptions;
 7using Elsa.Workflows.Models;
 8
 9// ReSharper disable once CheckNamespace
 10namespace Elsa.Extensions;
 11
 12public static partial class ActivityExecutionContextExtensions
 13{
 14    /// <param name="context">The <see cref="ActivityExecutionContext"/> being extended.</param>
 15    extension(ActivityExecutionContext context)
 16    {
 17        /// <summary>
 18        /// Evaluates each input property of the activity.
 19        /// </summary>
 20        public async Task EvaluateInputPropertiesAsync()
 21        {
 348022            var activityDescriptor = context.ActivityDescriptor;
 876223            var inputDescriptors = activityDescriptor.Inputs.Where(x => x.AutoEvaluate).ToList();
 24
 25            // Evaluate inputs.
 1739626            foreach (var inputDescriptor in inputDescriptors)
 522027                await EvaluateInputPropertyAsync(context, activityDescriptor, inputDescriptor);
 28
 347629            context.SetHasEvaluatedProperties();
 347630        }
 31
 32        /// <summary>
 33        /// Evaluates the specified input property of the activity.
 34        /// </summary>
 35        public async Task<T?> EvaluateInputPropertyAsync<TActivity, T>(Expression<Func<TActivity, Input<T>>> propertyExp
 36        {
 5137            var inputName = propertyExpression.GetProperty()!.Name;
 5138            var input = await EvaluateInputPropertyAsync(context, inputName);
 5039            return input.ConvertTo<T>();
 5040        }
 41
 42        /// <summary>
 43        /// Evaluates a specific input property of the activity.
 44        /// </summary>
 45        public async Task<object?> EvaluateInputPropertyAsync(string inputName)
 46        {
 5147            var activity = context.Activity;
 5148            var activityRegistryLookup = context.GetRequiredService<IActivityRegistryLookupService>();
 5149            var activityDescriptor = await activityRegistryLookup.FindAsync(activity.Type) ?? throw new Exception("Activ
 5150            var inputDescriptor = activityDescriptor.GetWrappedInputPropertyDescriptor(activity, inputName);
 51
 5152            if (inputDescriptor == null)
 053                throw new Exception($"No input with name {inputName} could be found");
 54
 5155            return await EvaluateInputPropertyAsync(context, activityDescriptor, inputDescriptor);
 5056        }
 57
 58        /// <summary>
 59        /// Evaluates the specified input and sets the result in the activity execution context's memory space.
 60        /// </summary>
 61        /// <param name="input">The input to evaluate.</param>
 62        /// <typeparam name="T">The type of the input.</typeparam>
 63        /// <returns>The evaluated value.</returns>
 64        public async Task<T?> EvaluateAsync<T>(Input<T> input)
 65        {
 066            var evaluator = context.GetRequiredService<IExpressionEvaluator>();
 067            var memoryBlockReference = input.MemoryBlockReference();
 068            var value = await evaluator.EvaluateAsync(input, context.ExpressionExecutionContext);
 069            memoryBlockReference.Set(context, value);
 070            return value;
 071        }
 72
 73        private async Task<object?> EvaluateInputPropertyAsync(ActivityDescriptor activityDescriptor, InputDescriptor in
 74        {
 75            try
 76            {
 527177                return await EvaluateInputPropertyCoreAsync(context, activityDescriptor, inputDescriptor);
 78            }
 579            catch (Exception e)
 80            {
 581                throw new InputEvaluationException(inputDescriptor.Name, $"Failed to evaluate activity input '{inputDesc
 82            }
 526683        }
 84
 85        private async Task<object?> EvaluateInputPropertyCoreAsync(ActivityDescriptor activityDescriptor, InputDescripto
 86        {
 527187            var activity = context.Activity;
 527188            var defaultValue = inputDescriptor.DefaultValue;
 527189            var value = defaultValue;
 527190            var input = inputDescriptor.ValueGetter(activity);
 527191            var identityGenerator = context.GetRequiredService<IIdentityGenerator>();
 92
 527193            if (inputDescriptor.IsWrapped)
 94            {
 434795                var wrappedInput = (Input?)input;
 96
 434797                if (defaultValue != null && wrappedInput == null)
 98                {
 999                    var typedInput = typeof(Input<>).MakeGenericType(inputDescriptor.Type);
 9100                    var valueExpression = new Literal(defaultValue)
 9101                    {
 9102                        Id = identityGenerator.GenerateId(),
 9103                    };
 9104                    wrappedInput = (Input)Activator.CreateInstance(typedInput, valueExpression)!;
 9105                    inputDescriptor.ValueSetter(activity, wrappedInput);
 106                }
 107                else
 108                {
 4338109                    var expressionEvaluator = context.GetRequiredService<IExpressionEvaluator>();
 4338110                    var expressionExecutionContext = context.ExpressionExecutionContext;
 4338111                    var inputEvaluatorType = inputDescriptor.EvaluatorType ?? typeof(DefaultActivityInputEvaluator);
 112
 4338113                    if (wrappedInput?.Expression != null)
 114                    {
 2508115                        var inputEvaluator = (IActivityInputEvaluator)context.GetRequiredService(inputEvaluatorType);
 2508116                        var inputEvaluatorContext = new ActivityInputEvaluatorContext(context, expressionExecutionContex
 2508117                        value = await inputEvaluator.EvaluateAsync(inputEvaluatorContext);
 118                    }
 119                }
 120
 4342121                var memoryReference = wrappedInput?.MemoryBlockReference();
 122
 4342123                if (memoryReference != null)
 124                {
 125                    // When input is created from an activity provider, there may be no memory block reference ID.
 2512126                    if (memoryReference.Id == null!)
 18127                        memoryReference.Id = $"{activity.NodeId}.{inputDescriptor.Name}"; // Construct a deterministic I
 128
 129                    // Declare the input memory block in the current context.
 2512130                    context.ExpressionExecutionContext.Set(memoryReference, value!);
 131                }
 4342132            }
 133            else
 134            {
 924135                value = input;
 136            }
 137
 5266138            await StoreInputValueAsync(context, inputDescriptor, value!);
 139
 5266140            return value;
 5266141        }
 142    }
 143
 144    private static Task StoreInputValueAsync(ActivityExecutionContext context, InputDescriptor inputDescriptor, object v
 145    {
 146        // Store the serialized input value in the activity state.
 147        // Serializing the value ensures we store a copy of the value and not a reference to the input, which may change
 5266148        if (inputDescriptor.IsSerializable != false)
 149        {
 150            // TODO: Disable filtering for now until we redesign log sanitization.
 151            // var serializedValue = await context.GetRequiredService<ISafeSerializer>().SerializeToElementAsync(value);
 152            // var manager = context.GetRequiredService<IActivityStateFilterManager>();
 153            // var filterContext = new ActivityStateFilterContext(context, inputDescriptor, serializedValue, context.Can
 154            // var filterResult = await manager.RunFiltersAsync(filterContext);
 5266155            context.ActivityState[inputDescriptor.Name] = value;
 156        }
 157
 5266158        return Task.CompletedTask;
 159    }
 160}

Methods/Properties

TryGetWorkflowInput(Elsa.Workflows.ActivityExecutionContext,System.String,T&,System.Text.Json.JsonSerializerOptions)
GetWorkflowInput(Elsa.Workflows.ActivityExecutionContext,System.Text.Json.JsonSerializerOptions)
GetWorkflowInput(Elsa.Workflows.ActivityExecutionContext,System.String,System.Text.Json.JsonSerializerOptions)
SetResult(Elsa.Workflows.ActivityExecutionContext,System.Object)
IsTriggerOfWorkflow(Elsa.Workflows.ActivityExecutionContext)
CreateVariable(Elsa.Workflows.ActivityExecutionContext,System.String,System.Object,System.Type,System.Action`1<Elsa.Expressions.Models.MemoryBlock>)
SetVariable(Elsa.Workflows.ActivityExecutionContext,System.String,System.Object,System.Action`1<Elsa.Expressions.Models.MemoryBlock>)
SetDynamicVariable(Elsa.Workflows.ActivityExecutionContext,System.String,T,System.Action`1<Elsa.Expressions.Models.MemoryBlock>)
GetVariable(Elsa.Workflows.ActivityExecutionContext,System.String)
GetVariableValues(Elsa.Workflows.ActivityExecutionContext)
GetActivitiesWithOutputs()
GetActivitiesWithOutputs()
FindActivityByIdOrName(Elsa.Workflows.ActivityExecutionContext,System.String)
GetOutcomeName(Elsa.Workflows.ActivityExecutionContext,System.String)
SendSignalAsync()
ScheduleOutcomesAsync()
CancelActivityAsync()
Fault(Elsa.Workflows.ActivityExecutionContext,System.Exception)
RecoverFromFault(Elsa.Workflows.ActivityExecutionContext)
FindParentWithVariableContainer(Elsa.Workflows.ActivityExecutionContext)
FindParent(Elsa.Workflows.ActivityExecutionContext,System.Func`2<Elsa.Workflows.ActivityExecutionContext,System.Boolean>)
GetAncestors()
GetDescendents()
GetActiveChildren(Elsa.Workflows.ActivityExecutionContext)
GetChildren(Elsa.Workflows.ActivityExecutionContext)
GetDescendants()
SetExtensionsMetadata(Elsa.Workflows.ActivityExecutionContext,System.String,System.Object)
GetExtensionsMetadata(Elsa.Workflows.ActivityExecutionContext)
GetActivityOutput(Elsa.Workflows.ActivityExecutionContext,System.Linq.Expressions.Expression`1<System.Func`1<TProp>>)
GetHasEvaluatedProperties(Elsa.Workflows.ActivityExecutionContext)
SetHasEvaluatedProperties(Elsa.Workflows.ActivityExecutionContext)
EvaluateInputPropertiesAsync()
EvaluateInputPropertyAsync()
EvaluateInputPropertyAsync()
EvaluateAsync()
EvaluateInputPropertyAsync()
EvaluateInputPropertyCoreAsync()
StoreInputValueAsync(Elsa.Workflows.ActivityExecutionContext,Elsa.Workflows.Models.InputDescriptor,System.Object)