< Summary

Information
Class: TeleFlow.Framework.Application.TeleFlowApplicationRuntimeFactory
Assembly: TeleFlow.Framework.Core
File(s): /_/src/TeleFlow.Framework.Core/Application/TeleFlowApplicationRuntimeFactory.cs
Line coverage
96%
Covered lines: 51
Uncovered lines: 2
Coverable lines: 53
Total lines: 112
Line coverage: 96.2%
Branch coverage
78%
Covered branches: 11
Total branches: 14
Branch coverage: 78.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
CreateOwned(...)100%11100%
CreateBorrowed(...)50%22100%
Create(...)100%11100%
ResolveSingleRequiredService(...)75%4477.77%
ValidateServiceDescriptors(...)87.5%88100%

File(s)

/_/src/TeleFlow.Framework.Core/Application/TeleFlowApplicationRuntimeFactory.cs

#LineLine coverage
 1using Microsoft.Extensions.DependencyInjection;
 2using TeleFlow.Framework.DependencyInjection;
 3using TeleFlow.Framework.Dispatching;
 4using TeleFlow.Framework.Middleware;
 5using TeleFlow.Framework.Updates;
 6
 7namespace TeleFlow.Framework.Application;
 8
 9/// <summary>
 10/// Composes the Core runtime pipeline from registered services: update source, update processor,
 11/// dispatcher, middleware, and application lifecycle tasks.
 12/// </summary>
 13internal static class TeleFlowApplicationRuntimeFactory
 14{
 15    public static ITeleFlowApplication CreateOwned(IServiceCollection services)
 16    {
 5417        ArgumentNullException.ThrowIfNull(services);
 18
 5419        ValidateServiceDescriptors(services);
 20
 5121        var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions
 5122        {
 5123            ValidateOnBuild = true,
 5124            ValidateScopes = true
 5125        });
 26
 27        try
 28        {
 5129            return Create(serviceProvider, ownsServices: true);
 30        }
 631        catch
 32        {
 633            serviceProvider.Dispose();
 634            throw;
 35        }
 4536    }
 37
 38    public static ITeleFlowApplication CreateBorrowed(
 39        IServiceProvider serviceProvider,
 40        IEnumerable<ServiceDescriptor>? serviceDescriptors = null)
 41    {
 442        ArgumentNullException.ThrowIfNull(serviceProvider);
 43
 444        if (serviceDescriptors is not null)
 45        {
 446            ValidateServiceDescriptors(serviceDescriptors);
 47        }
 48
 349        return Create(serviceProvider, ownsServices: false);
 50    }
 51
 52    private static ITeleFlowApplication Create(IServiceProvider serviceProvider, bool ownsServices)
 53    {
 5454        TeleFlowRuntimeValidatorRunner.Validate(serviceProvider);
 55
 5056        var scopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
 5057        var updateSource = ResolveSingleRequiredService<IUpdateSource>(serviceProvider);
 4958        var dispatcher = ResolveSingleRequiredService<IUpdateDispatcher>(serviceProvider);
 4859        var middleware = serviceProvider.GetServices<UpdateMiddlewareRegistration>().ToArray();
 4860        var startupTasks = serviceProvider.GetServices<TeleFlowStartupTaskRegistration>().ToArray();
 4861        var shutdownTasks = serviceProvider.GetServices<TeleFlowShutdownTaskRegistration>().ToArray();
 4862        var processor = new DefaultUpdateProcessor(scopeFactory, dispatcher, middleware);
 4863        var lifecycle = new TeleFlowApplicationLifecycleRunner(scopeFactory, startupTasks, shutdownTasks);
 64
 4865        return new TeleFlowApplication(serviceProvider, updateSource, processor, lifecycle, ownsServices);
 66    }
 67
 68    private static TService ResolveSingleRequiredService<TService>(IServiceProvider serviceProvider)
 69        where TService : class
 70    {
 9971        var services = serviceProvider.GetServices<TService>().ToArray();
 72
 9973        return services.Length switch
 9974        {
 275            0 => throw new InvalidOperationException(
 276                $"A single {typeof(TService).Name} registration is required to build the TeleFlow application."),
 077            > 1 => throw new InvalidOperationException(
 078                $"Only one {typeof(TService).Name} registration is supported when building the TeleFlow application."),
 9779            _ => services[0]
 9980        };
 81    }
 82
 83    private static void ValidateServiceDescriptors(IEnumerable<ServiceDescriptor> services)
 84    {
 5885        var descriptors = services as ICollection<ServiceDescriptor> ?? services.ToArray();
 86
 139987        if (descriptors.Any(static descriptor => descriptor.ServiceType == typeof(IUpdateMiddleware)))
 88        {
 289            throw new InvalidOperationException(
 290                "Direct IUpdateMiddleware service registrations are not used by the TeleFlow update pipeline. " +
 291                $"Register middleware with {nameof(ServiceCollectionMiddlewareExtensions.AddUpdateMiddleware)}<TMiddlewa
 292                $"or {nameof(ServiceCollectionMiddlewareExtensions.AddSingletonUpdateMiddleware)}<TMiddleware>() so Tele
 293                "resolve it from the correct update scope.");
 94        }
 95
 138496        if (descriptors.Any(static descriptor => descriptor.ServiceType == typeof(ITeleFlowStartupTask)))
 97        {
 198            throw new InvalidOperationException(
 199                "Direct ITeleFlowStartupTask service registrations are not used by the TeleFlow application lifecycle. "
 1100                $"Register startup tasks with {nameof(ApplicationLifecycleServiceCollectionExtensions.AddTeleFlowStartup
 1101                "so TeleFlow can resolve them from a dedicated lifecycle scope.");
 102        }
 103
 1375104        if (descriptors.Any(static descriptor => descriptor.ServiceType == typeof(ITeleFlowShutdownTask)))
 105        {
 1106            throw new InvalidOperationException(
 1107                "Direct ITeleFlowShutdownTask service registrations are not used by the TeleFlow application lifecycle. 
 1108                $"Register shutdown tasks with {nameof(ApplicationLifecycleServiceCollectionExtensions.AddTeleFlowShutdo
 1109                "so TeleFlow can resolve them from a dedicated lifecycle scope.");
 110        }
 54111    }
 112}