< Summary

Information
Class: Elsa.Workflows.OutputConverterInvoker
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Services/OutputConverterInvoker.cs
Line coverage
85%
Covered lines: 40
Uncovered lines: 7
Coverable lines: 47
Total lines: 106
Line coverage: 85.1%
Branch coverage
79%
Covered branches: 19
Total branches: 24
Branch coverage: 79.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Invoke(...)75%272074.19%
CreateException()100%11100%
IsRuntimeValueCompatible(...)75%44100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Services/OutputConverterInvoker.cs

#LineLine coverage
 1using Elsa.Workflows.Exceptions;
 2using Elsa.Workflows.Models;
 3using Microsoft.Extensions.DependencyInjection;
 4
 5namespace Elsa.Workflows;
 6
 7/// <inheritdoc />
 148public class OutputConverterInvoker(
 149    IOutputConverterRegistry registry,
 1410    IOutputConverterSettingsValidator settingsValidator) : IOutputConverterInvoker
 11{
 12    /// <inheritdoc />
 13    public object? Invoke(
 14        ActivityExecutionContext activityExecutionContext,
 15        Output output,
 16        string outputName,
 17        Type sourceType,
 18        object value,
 19        OutputBindingDestination destination)
 20    {
 1621        var configuration = output.Converter ?? throw new InvalidOperationException("The output binding has no converter
 1622        var descriptor = registry.Find(configuration.Id);
 23
 1624        if (descriptor == null)
 125            throw CreateException(OutputConversionFailureStage.Resolution);
 26
 1527        if (!IsRuntimeValueCompatible(value, sourceType) || !descriptor.SourceType.IsAssignableFrom(sourceType))
 128            throw CreateException(OutputConversionFailureStage.SourceCompatibility);
 29
 1430        if (!OutputConverterRegistry.IsAssignableToDestination(descriptor.ResultType, destination.Type))
 231            throw CreateException(OutputConversionFailureStage.ResultValidation);
 32
 33        IOutputConverter converter;
 34
 35        try
 36        {
 1237            converter = activityExecutionContext.WorkflowExecutionContext.ServiceProvider
 1238                .GetRequiredKeyedService<IOutputConverter>(configuration.Id);
 1239        }
 040        catch (Exception e)
 41        {
 042            throw CreateException(OutputConversionFailureStage.Resolution, e);
 43        }
 44
 45        IReadOnlyCollection<string> settingsErrors;
 46
 47        try
 48        {
 1249            settingsErrors = settingsValidator.Validate(descriptor, converter, configuration.Settings);
 1250        }
 051        catch (Exception e)
 52        {
 053            throw CreateException(OutputConversionFailureStage.SettingsValidation, e);
 54        }
 55
 1256        if (settingsErrors.Count > 0)
 257            throw CreateException(OutputConversionFailureStage.SettingsValidation);
 58
 59        object? convertedValue;
 60
 61        try
 62        {
 1063            convertedValue = converter.Convert(new(value, sourceType, destination.Type, configuration.Settings));
 964        }
 165        catch (Exception e)
 66        {
 167            throw CreateException(OutputConversionFailureStage.Invocation, e);
 68        }
 69
 970        if (convertedValue == null)
 71        {
 072            if (!destination.AllowsNull)
 073                throw CreateException(OutputConversionFailureStage.ResultValidation);
 74
 075            return null;
 76        }
 77
 978        if (!IsRuntimeValueCompatible(convertedValue, descriptor.ResultType) ||
 979            !IsRuntimeValueCompatible(convertedValue, destination.Type))
 80        {
 181            throw CreateException(OutputConversionFailureStage.ResultValidation);
 82        }
 83
 884        return convertedValue;
 85
 86        OutputConversionException CreateException(OutputConversionFailureStage stage, Exception? innerException = null) 
 887            new(
 888                configuration.Id,
 889                stage,
 890                activityExecutionContext.Activity.Id,
 891                activityExecutionContext.Activity.Type,
 892                outputName,
 893                destination.Id,
 894                sourceType,
 895                destination.Type,
 896                innerException);
 97    }
 98
 99    private static bool IsRuntimeValueCompatible(object value, Type declaredType)
 100    {
 32101        if (declaredType.IsInstanceOfType(value))
 31102            return true;
 103
 1104        return Nullable.GetUnderlyingType(declaredType)?.IsInstanceOfType(value) == true;
 105    }
 106}