< Summary

Information
Class: NexusLabs.Needlr.ServiceProviderExtensions
Assembly: NexusLabs.Needlr
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr/ServiceProviderExtensions.cs
Line coverage
92%
Covered lines: 50
Uncovered lines: 4
Coverable lines: 54
Total lines: 231
Line coverage: 92.5%
Branch coverage
100%
Covered branches: 14
Total branches: 14
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetRegisteredTypes(...)100%22100%
GetRegisteredTypesOf(...)100%22100%
IsRegistered(...)100%11100%
IsRegistered(...)100%11100%
GetServiceRegistrations(...)100%210%
GetServiceRegistrations(...)100%11100%
GetServiceCollection(...)100%22100%
CopyRegistrationsToServiceCollection(...)100%8894.11%
CopyRegistrationsToServiceCollection(...)100%11100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr/ServiceProviderExtensions.cs

#LineLine coverage
 1using Microsoft.Extensions.DependencyInjection;
 2
 3using System;
 4
 5namespace NexusLabs.Needlr;
 6
 7/// <summary>
 8/// Extension methods for <see cref="IServiceProvider"/> to provide type inspection functionality.
 9/// </summary>
 10public static class ServiceProviderExtensions
 11{
 12    /// <summary>
 13    /// Gets all registered service types that match the specified predicate without instantiating the services.
 14    /// </summary>
 15    /// <param name="serviceProvider">The service provider to inspect.</param>
 16    /// <param name="predicate">A function to filter the service types.</param>
 17    /// <returns>A read-only list of types that match the predicate.</returns>
 18    /// <exception cref="ArgumentNullException">Thrown when serviceProvider or predicate is null.</exception>
 19    /// <exception cref="InvalidOperationException">Thrown when the service collection is not accessible.</exception>
 20    /// <example>
 21    /// <code>
 22    /// // Get all interface types
 23    /// var interfaceTypes = serviceProvider.GetRegisteredTypes(type => type.IsInterface);
 24    ///
 25    /// // Get all types in a specific namespace
 26    /// var myNamespaceTypes = serviceProvider.GetRegisteredTypes(type =>
 27    ///     type.Namespace?.StartsWith("MyApp.Services") == true);
 28    ///
 29    /// // Get all types implementing a specific interface
 30    /// var repositoryTypes = serviceProvider.GetRegisteredTypes(type =>
 31    ///     typeof(IRepository).IsAssignableFrom(type));
 32    /// </code>
 33    /// </example>
 34    public static IEnumerable<Type> GetRegisteredTypes(
 35        this IServiceProvider serviceProvider,
 36        Func<Type, bool> predicate)
 37    {
 3538        ArgumentNullException.ThrowIfNull(serviceProvider);
 3339        ArgumentNullException.ThrowIfNull(predicate);
 40
 41        // Try to get the service collection from the service provider
 42        // This works with most DI containers including the default Microsoft container
 3243        var serviceCollection = serviceProvider.GetService<IServiceCollection>()
 3244            ?? throw new InvalidOperationException(
 3245                "Unable to access the service collection from the service provider. " +
 3246                "Ensure the IServiceCollection is registered in the container.");
 47
 3148        return serviceCollection
 617749            .Select(descriptor => descriptor.ServiceType)
 3150            .Distinct()
 3151            .Where(predicate);
 52    }
 53
 54    /// <summary>
 55    /// Gets all registered service types that implement or inherit from the specified type without instantiating the se
 56    /// </summary>
 57    /// <typeparam name="T">The base type or interface to filter by.</typeparam>
 58    /// <param name="serviceProvider">The service provider to inspect.</param>
 59    /// <returns>A read-only list of types that implement or inherit from T.</returns>
 60    /// <exception cref="ArgumentNullException">Thrown when serviceProvider is null.</exception>
 61    /// <example>
 62    /// <code>
 63    /// // Get all types implementing IRepository
 64    /// var repositoryTypes = serviceProvider.GetRegisteredTypesOf&lt;IRepository&gt;();
 65    ///
 66    /// // Get all types inheriting from BaseService
 67    /// var serviceTypes = serviceProvider.GetRegisteredTypesOf&lt;BaseService&gt;();
 68    /// </code>
 69    /// </example>
 70    public static IEnumerable<Type> GetRegisteredTypesOf<T>(this IServiceProvider serviceProvider)
 71    {
 1572        return serviceProvider
 198673            .GetRegisteredTypes(type => typeof(T)
 198674            .IsAssignableFrom(type));
 75    }
 76
 77    /// <summary>
 78    /// Determines whether a service of the specified type is registered in the service provider.
 79    /// </summary>
 80    /// <typeparam name="TService">The service type to check.</typeparam>
 81    /// <param name="serviceProvider">The service provider to check.</param>
 82    /// <returns>True if the service is registered; otherwise, false.</returns>
 83    public static bool IsRegistered<TService>(this IServiceProvider serviceProvider)
 84    {
 485        ArgumentNullException.ThrowIfNull(serviceProvider);
 386        return serviceProvider.IsRegistered(typeof(TService));
 87    }
 88
 89    /// <summary>
 90    /// Determines whether a service of the specified type is registered in the service provider.
 91    /// </summary>
 92    /// <param name="serviceProvider">The service provider to check.</param>
 93    /// <param name="serviceType">The service type to check.</param>
 94    /// <returns>True if the service is registered; otherwise, false.</returns>
 95    public static bool IsRegistered(
 96        this IServiceProvider serviceProvider,
 97        Type serviceType)
 98    {
 699        ArgumentNullException.ThrowIfNull(serviceProvider);
 5100        return serviceProvider
 5101            .GetServiceCollection()
 5102            .IsRegistered(serviceType);
 103    }
 104
 105    /// <summary>
 106    /// Gets detailed information about all registered services.
 107    /// </summary>
 108    /// <param name="serviceProvider">The service provider to inspect.</param>
 109    /// <returns>A read-only list of service registration information.</returns>
 110    /// <exception cref="ArgumentNullException">Thrown when serviceProvider is null.</exception>
 111    /// <example>
 112    /// <code>
 113    /// // Get all singleton services
 114    /// var singletons = serviceProvider.GetServiceRegistrations(
 115    ///     descriptor => descriptor.Lifetime == ServiceLifetime.Singleton);
 116    ///
 117    /// // Get all services with a specific implementation type
 118    /// var specificImpls = serviceProvider.GetServiceRegistrations(
 119    ///     descriptor => descriptor.ImplementationType == typeof(MyService));
 120    /// </code>
 121    /// </example>
 122    public static IReadOnlyList<ServiceRegistrationInfo> GetServiceRegistrations(
 123        this IServiceProvider serviceProvider)
 124    {
 0125        ArgumentNullException.ThrowIfNull(serviceProvider);
 126
 0127        return serviceProvider
 0128            .GetServiceCollection()
 0129            .GetServiceRegistrations();
 130    }
 131
 132    /// <summary>
 133    /// Gets detailed information about all registered services that match the specified predicate.
 134    /// </summary>
 135    /// <param name="serviceProvider">The service provider to inspect.</param>
 136    /// <param name="predicate">A function to filter the service descriptors.</param>
 137    /// <returns>A read-only list of service registration information.</returns>
 138    /// <exception cref="ArgumentNullException">Thrown when serviceProvider or predicate is null.</exception>
 139    /// <example>
 140    /// <code>
 141    /// // Get all singleton services
 142    /// var singletons = serviceProvider.GetServiceRegistrations(
 143    ///     descriptor => descriptor.Lifetime == ServiceLifetime.Singleton);
 144    ///
 145    /// // Get all services with a specific implementation type
 146    /// var specificImpls = serviceProvider.GetServiceRegistrations(
 147    ///     descriptor => descriptor.ImplementationType == typeof(MyService));
 148    /// </code>
 149    /// </example>
 150    public static IReadOnlyList<ServiceRegistrationInfo> GetServiceRegistrations(
 151        this IServiceProvider serviceProvider,
 152        Func<ServiceDescriptor, bool> predicate)
 153    {
 57154        ArgumentNullException.ThrowIfNull(serviceProvider);
 56155        ArgumentNullException.ThrowIfNull(predicate);
 156
 55157        return serviceProvider
 55158            .GetServiceCollection()
 55159            .GetServiceRegistrations(predicate);
 160    }
 161
 162    /// <summary>
 163    /// Gets the service collection from the service provider.
 164    /// </summary>
 165    /// <param name="serviceProvider">The service provider.</param>
 166    /// <returns>The service collection.</returns>
 167    /// <exception cref="InvalidOperationException">Thrown when the service collection is not available.</exception>
 168    public static IServiceCollection GetServiceCollection(
 169        this IServiceProvider serviceProvider)
 170    {
 68171        ArgumentNullException.ThrowIfNull(serviceProvider);
 172
 67173        return serviceProvider.GetService<IServiceCollection>()
 67174            ?? throw new InvalidOperationException(
 67175                "Unable to access the service collection from the service provider. " +
 67176                "Ensure the IServiceCollection is registered in the container.");
 177    }
 178
 179    /// <summary>
 180    /// Copies all service registrations from the service provider to the specified service collection.
 181    /// </summary>
 182    /// <param name="serviceProvider">The source service provider.</param>
 183    /// <param name="serviceCollection">The target service collection.</param>
 184    public static void CopyRegistrationsToServiceCollection(
 185        this IServiceProvider serviceProvider,
 186        IServiceCollection serviceCollection)
 187    {
 45188        ArgumentNullException.ThrowIfNull(serviceProvider);
 44189        ArgumentNullException.ThrowIfNull(serviceCollection);
 190
 3581191        foreach (var registration in serviceProvider.GetServiceRegistrations(_ => true))
 192        {
 1165193            if (registration.ServiceType == typeof(IServiceProvider))
 194            {
 195                continue;
 196            }
 197
 1134198            if (registration.ServiceDescriptor.ServiceType.IsGenericTypeDefinition)
 199            {
 94200                serviceCollection.Add(registration.ServiceDescriptor);
 94201                continue;
 202            }
 203
 1040204            var descriptor = registration.Lifetime switch
 1040205            {
 1032206                ServiceLifetime.Singleton => new ServiceDescriptor(
 1032207                    registration.ServiceType,
 19208                    _ => serviceProvider.GetRequiredService(registration.ServiceType),
 1032209                    ServiceLifetime.Singleton),
 8210                _ => registration.ServiceDescriptor
 1040211            };
 212
 1040213            serviceCollection.Add(descriptor);
 214        }
 43215    }
 216
 217    /// <summary>
 218    /// Copies all service registrations from the service provider to a new service collection.
 219    /// </summary>
 220    /// <param name="serviceProvider">The source service provider.</param>
 221    /// <returns>A new service collection containing all registrations.</returns>
 222    public static IServiceCollection CopyRegistrationsToServiceCollection(
 223        this IServiceProvider serviceProvider)
 224    {
 4225        ArgumentNullException.ThrowIfNull(serviceProvider);
 226
 3227        ServiceCollection serviceCollection = new();
 3228        serviceProvider.CopyRegistrationsToServiceCollection(serviceCollection);
 3229        return serviceCollection;
 230    }
 231}