< Summary

Information
Class: IceRpc.Extensions.DependencyInjection.ServerServiceCollectionExtensions
Assembly: IceRpc.Extensions.DependencyInjection
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Extensions.DependencyInjection/ServerServiceCollectionExtensions.cs
Tag: 2300_35243572715
Line coverage
82%
Covered lines: 39
Uncovered lines: 8
Coverable lines: 47
Total lines: 173
Line coverage: 82.9%
Branch coverage
0%
Covered branches: 0
Total branches: 6
Branch coverage: 0%
Method coverage
85%
Covered methods: 6
Fully covered methods: 5
Total methods: 7
Method coverage: 85.7%
Full method coverage: 71.4%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddIceRpcServer(...)100%210%
AddIceRpcServer(...)100%11100%
AddIceRpcServer(...)100%11100%
AddIceRpcServer(...)100%11100%
AddIceRpcServer(...)100%11100%
AddIceRpcServer(...)100%11100%
TryAddIceRpcServerTransport(...)0%7666.66%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Extensions.DependencyInjection/ServerServiceCollectionExtensions.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using IceRpc.Extensions.DependencyInjection.Internal;
 4using IceRpc.Transports;
 5using IceRpc.Transports.Quic;
 6using IceRpc.Transports.Tcp;
 7using Microsoft.Extensions.DependencyInjection;
 8using Microsoft.Extensions.DependencyInjection.Extensions;
 9using Microsoft.Extensions.Logging;
 10using Microsoft.Extensions.Options;
 11
 12namespace IceRpc.Extensions.DependencyInjection;
 13
 14/// <summary>Provides extension methods for <see cref="IServiceCollection" /> to add a <see cref="Server" />.</summary>
 15public static class ServerServiceCollectionExtensions
 16{
 17    /// <summary>Adds a <see cref="Server" /> with the specified dispatch pipeline to this service collection; you can
 18    /// specify the server's options by injecting an <see cref="IOptions{T}" /> of <see cref="ServerOptions" />.
 19    /// </summary>
 20    /// <param name="services">The service collection to add services to.</param>
 21    /// <param name="dispatcher">The dispatch pipeline.</param>
 22    /// <returns>The service collection.</returns>
 23    /// <example>
 24    /// The following code adds a Server singleton to the service collection.
 25    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
 26    /// region="DefaultServer" lang="csharp" />
 27    /// The resulting singleton is a default server: it uses the default server address and the default multiplexed
 28    /// transport (QUIC). If you want to customize this server, add an <see cref="IOptions{T}" /> of
 29    /// <see cref="ServerOptions" /> to your DI container:
 30    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
 31    /// region="ServerWithOptions" lang="csharp" />
 32    /// You can also inject a server transport:
 33    /// <list type="bullet">
 34    /// <item><description>an <see cref="IDuplexServerTransport" /> for the ice protocol</description></item>
 35    /// <item><description>an <see cref="IMultiplexedServerTransport" /> for the icerpc protocol</description></item>
 36    /// </list>
 37    ///
 38    /// For example, you can add a Slic over TCP server as follows:
 39    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
 40    /// region="ServerWithSlic" lang="csharp" />
 41    /// If you want to customize the options of the default transport (QUIC), you just need to inject
 42    /// an <see cref="IOptions{T}" /> of <see cref="QuicServerTransportOptions" />.
 43    /// </example>
 44    public static IServiceCollection AddIceRpcServer(this IServiceCollection services, IDispatcher dispatcher) =>
 045        services.AddIceRpcServer(optionsName: Options.DefaultName, dispatcher);
 46
 47    /// <summary>Adds a <see cref="Server" /> to this service collection and configures the dispatch pipeline of this
 48    /// server; you can specify the server's options by injecting an <see cref="IOptions{T}" /> of
 49    /// <see cref="ServerOptions" />.
 50    /// </summary>
 51    /// <param name="services">The service collection to add services to.</param>
 52    /// <param name="configure">The action to configure the dispatch pipeline using an
 53    /// <see cref="IDispatcherBuilder" />.</param>
 54    /// <returns>The service collection.</returns>
 55    /// <remarks>The dispatch pipeline built by this method is not registered in the DI container.</remarks>
 56    /// <example>
 57    /// The following code builds a dispatch pipeline and adds a server with this dispatch pipeline to the service
 58    /// collection.
 59    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
 60    /// region="ServerWithDispatcherBuilder"
 61    /// lang="csharp" />
 62    /// See also <see cref="AddIceRpcServer(IServiceCollection, IDispatcher)" />.
 63    /// </example>
 64    public static IServiceCollection AddIceRpcServer(
 65        this IServiceCollection services,
 66        Action<IDispatcherBuilder> configure) =>
 267        services.AddIceRpcServer(optionsName: Options.DefaultName, configure);
 68
 69    /// <summary>Adds a <see cref="Server" /> to this service collection; you specify the server's options by injecting
 70    /// an <see cref="IOptions{T}" /> of <see cref="ServerOptions" />.</summary>
 71    /// <param name="services">The service collection to add services to.</param>
 72    /// <returns>The service collection.</returns>
 73    /// <remarks>You need to set a least the dispatcher in the injected options.</remarks>
 74    public static IServiceCollection AddIceRpcServer(this IServiceCollection services) =>
 2575        services.AddIceRpcServer(Options.DefaultName);
 76
 77    /// <summary>Adds a <see cref="Server" /> with the specified dispatch pipeline to this service collection; you can
 78    /// specify the server's options by injecting an <see cref="IOptionsMonitor{T}" /> of <see cref="ServerOptions" />
 79    /// named <paramref name="optionsName" />.</summary>
 80    /// <param name="services">The service collection to add services to.</param>
 81    /// <param name="optionsName">The name of the options instance. Each <see cref="Server" /> registered in
 82    /// <paramref name="services" /> must use a unique options name.</param>
 83    /// <param name="dispatcher">The dispatch pipeline of the server.</param>
 84    /// <returns>The service collection.</returns>
 85    /// <example>
 86    /// A server application may need to host multiple <see cref="Server" /> instances, each with its own options. A
 87    /// typical example is when you want to accept requests from clients over both the icerpc protocol and the ice
 88    /// protocol. This overload allows you to add two (or more) server singletons, each with its own options:
 89    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
 90    /// region="ServerWithNamedOptions" lang="csharp" />
 91    /// See also <see cref="AddIceRpcServer(IServiceCollection, IDispatcher)" />.
 92    /// </example>
 93    public static IServiceCollection AddIceRpcServer(
 94        this IServiceCollection services,
 95        string optionsName,
 96        IDispatcher dispatcher)
 297    {
 298        services.AddOptions<ServerOptions>(optionsName).Configure(
 499            options => options.ConnectionOptions.Dispatcher = dispatcher);
 2100        return services.AddIceRpcServer(optionsName);
 2101    }
 102
 103    /// <summary>Adds a <see cref="Server" /> to this service collection and configures the dispatch pipeline of this
 104    /// server; you can specify the server's options by injecting an <see cref="IOptionsMonitor{T}" /> of
 105    /// <see cref="ServerOptions" /> named <paramref name="optionsName" />.</summary>
 106    /// <param name="services">The service collection to add services to.</param>
 107    /// <param name="optionsName">The name of the options instance. Each <see cref="Server" /> registered in
 108    /// <paramref name="services" /> must use a unique options name.</param>
 109    /// <param name="configure">The action to configure the dispatch pipeline using an
 110    /// <see cref="IDispatcherBuilder" />.</param>
 111    /// <returns>The service collection.</returns>
 112    /// <remarks>The dispatch pipeline built by this method is not registered in the DI container.</remarks>
 113    /// <seealso cref="AddIceRpcServer(IServiceCollection, string, IDispatcher)" />
 114    public static IServiceCollection AddIceRpcServer(
 115        this IServiceCollection services,
 116        string optionsName,
 117        Action<IDispatcherBuilder> configure)
 10118    {
 10119        services.AddOptions<ServerOptions>(optionsName).Configure<IServiceProvider>(
 10120            (options, provider) =>
 10121            {
 10122                var dispatcherBuilder = new DispatcherBuilder(provider);
 10123                configure(dispatcherBuilder);
 10124                options.ConnectionOptions.Dispatcher = dispatcherBuilder.Build();
 20125            });
 10126        return services.AddIceRpcServer(optionsName);
 10127    }
 128
 129    /// <summary>Adds a <see cref="Server" /> to this service collection; you specify the server's options by injecting
 130    /// an <see cref="IOptionsMonitor{T}" /> of <see cref="ServerOptions" /> named <paramref name="optionsName" />.
 131    /// </summary>
 132    /// <param name="services">The service collection to add services to.</param>
 133    /// <param name="optionsName">The name of the options instance. Each <see cref="Server" /> registered in
 134    /// <paramref name="services" /> must use a unique options name.</param>
 135    /// <returns>The service collection.</returns>
 136    /// <remarks>You need to set at least the dispatcher in the injected options.</remarks>
 137    /// <seealso cref="AddIceRpcServer(IServiceCollection, string, IDispatcher)" />
 138    public static IServiceCollection AddIceRpcServer(this IServiceCollection services, string optionsName) =>
 37139        services
 37140            .TryAddIceRpcServerTransport()
 37141            .AddSingleton(provider =>
 71142                new Server(
 71143                    provider.GetRequiredService<IOptionsMonitor<ServerOptions>>().Get(optionsName),
 71144                    provider.GetRequiredService<IDuplexServerTransport>(),
 71145                    provider.GetRequiredService<IMultiplexedServerTransport>(),
 71146                    provider.GetService<ILogger<Server>>()));
 147
 148    private static IServiceCollection TryAddIceRpcServerTransport(this IServiceCollection services)
 37149    {
 150        // The default duplex transport is TCP.
 37151        services
 37152           .AddOptions()
 37153           .TryAddSingleton<IDuplexServerTransport>(
 37154               provider => new TcpServerTransport(
 37155                   provider.GetRequiredService<IOptions<TcpServerTransportOptions>>().Value));
 156
 37157        services
 37158            .TryAddSingleton<IMultiplexedServerTransport>(
 37159                provider =>
 0160                {
 0161                    if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsWindows())
 0162                    {
 37163                        // This works even when QUIC is not available.
 0164                        return new QuicServerTransport(
 0165                            provider.GetRequiredService<IOptions<QuicServerTransportOptions>>().Value);
 37166                    }
 0167                    throw new PlatformNotSupportedException(
 0168                        "The default QUIC server transport is not supported on this platform. You need to register an IM
 37169                });
 170
 37171        return services;
 37172    }
 173}