< Summary

Information
Class: Elsa.Expressions.CSharp.Handlers.GenerateWorkflowVariableAccessors
Assembly: Elsa.Expressions.CSharp
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Expressions.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs
Line coverage
3%
Covered lines: 1
Uncovered lines: 28
Coverable lines: 29
Total lines: 64
Line coverage: 3.4%
Branch coverage
0%
Covered branches: 0
Total branches: 8
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
HandleAsync(...)0%7280%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Expressions.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs

#LineLine coverage
 1using System.Dynamic;
 2using System.Text;
 3using Elsa.Expressions.CSharp.Extensions;
 4using Elsa.Expressions.CSharp.Notifications;
 5using Elsa.Expressions.CSharp.Options;
 6using Elsa.Expressions.Models;
 7using Elsa.Extensions;
 8using Elsa.Mediator.Contracts;
 9using Humanizer;
 10using JetBrains.Annotations;
 11using Microsoft.Extensions.Options;
 12
 13namespace Elsa.Expressions.CSharp.Handlers;
 14
 15/// <summary>
 16/// Configures the C# evaluator with methods to access workflow variables.
 17/// </summary>
 18[UsedImplicitly]
 31919public class GenerateWorkflowVariableAccessors(IOptions<CSharpOptions> options) : INotificationHandler<EvaluatingCSharp>
 20{
 21    /// <inheritdoc />
 22    public Task HandleAsync(EvaluatingCSharp notification, CancellationToken cancellationToken)
 23    {
 024        var expressionExecutionContext = notification.Context;
 025        var variables = expressionExecutionContext.GetVariablesInScope().ToList();
 026        var sb = new StringBuilder();
 027        sb.AppendLine("public partial class WorkflowVariablesProxy {");
 028        sb.AppendLine("\tpublic WorkflowVariablesProxy(ExecutionContextProxy executionContext) => ExecutionContext = exe
 029        sb.AppendLine("\tpublic ExecutionContextProxy ExecutionContext { get; }");
 030        sb.AppendLine();
 031        sb.AppendLine("\tpublic T? Get<T>(string name) => ExecutionContext.GetVariable<T>(name);");
 032        sb.AppendLine("\tpublic object? Get(string name) => ExecutionContext.GetVariable(name);");
 033        sb.AppendLine("\tpublic void Set(string name, object? value) => ExecutionContext.SetVariable(name, value);");
 034        sb.AppendLine();
 35
 036        if (!options.Value.DisableWrappers)
 37        {
 038            foreach (var variable in variables.Where(x => x.Name.IsValidVariableName()))
 39            {
 040                var variableName = variable.Name.Pascalize();
 041                var variableType = variable.GetVariableType();
 42
 43                // Check if the variable type is ExpandoObject
 044                bool isExpandoObject = variableType == typeof(ExpandoObject);
 45
 46                // Use dynamic type for ExpandoObject to enable dot notation but keep the original type for retrieval
 047                var displayTypeName = isExpandoObject ? "dynamic" : variableType.GetFriendlyTypeName(Brackets.Angle);
 048                var retrieveTypeName = isExpandoObject ? "ExpandoObject" : displayTypeName;
 49
 050                sb.AppendLine($"\tpublic {displayTypeName} {variableName}");
 051                sb.AppendLine("\t{");
 052                sb.AppendLine($"\t\tget => Get<{retrieveTypeName}>(\"{variableName}\");");
 053                sb.AppendLine($"\t\tset => Set(\"{variableName}\", value);");
 054                sb.AppendLine("\t}");
 55            }
 56        }
 57
 058        sb.AppendLine("}");
 059        sb.AppendLine("var Variables = new WorkflowVariablesProxy(ExecutionContext);"); // Obsolete; use Variable instea
 060        sb.AppendLine("var Variable = Variables;");
 061        notification.AppendScript(sb.ToString());
 062        return Task.CompletedTask;
 63    }
 64}