• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

icerpc / icerpc-csharp / 20832043296

08 Jan 2026 09:16PM UTC coverage: 83.413% (-0.2%) from 83.609%
20832043296

Pull #4217

github

web-flow
Merge 97165da25 into 07ee5cc03
Pull Request #4217: Rework exception when QUIC is not supported / available

12059 of 14457 relevant lines covered (83.41%)

2941.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.18
src/IceRpc.Extensions.DependencyInjection/ServerServiceCollectionExtensions.cs
1
// Copyright (c) ZeroC, Inc.
2

3
using IceRpc.Extensions.DependencyInjection.Internal;
4
using IceRpc.Transports;
5
using IceRpc.Transports.Quic;
6
using IceRpc.Transports.Tcp;
7
using Microsoft.Extensions.DependencyInjection;
8
using Microsoft.Extensions.DependencyInjection.Extensions;
9
using Microsoft.Extensions.Logging;
10
using Microsoft.Extensions.Options;
11
using System.Net.Quic;
12

13
namespace IceRpc.Extensions.DependencyInjection;
14

15
/// <summary>Provides extension methods for <see cref="IServiceCollection" /> to add a <see cref="Server" />.</summary>
16
public static class ServerServiceCollectionExtensions
17
{
18
    /// <summary>Adds a <see cref="Server" /> with the specified dispatch pipeline to this service collection; you can
19
    /// specify the server's options by injecting an <see cref="IOptions{T}" /> of <see cref="ServerOptions" />.
20
    /// </summary>
21
    /// <param name="services">The service collection to add services to.</param>
22
    /// <param name="dispatcher">The dispatch pipeline.</param>
23
    /// <returns>The service collection.</returns>
24
    /// <example>
25
    /// The following code adds a Server singleton to the service collection.
26
    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
27
    /// region="DefaultServer" lang="csharp" />
28
    /// The resulting singleton is a default server: it uses the default server address, the default multiplexed
29
    /// transport (tcp) and <c>null</c> for its authentication options (so no TLS). If you want to customize this
30
    /// server, add an <see cref="IOptions{T}" /> of <see cref="ServerOptions" /> to your DI container:
31
    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
32
    /// region="ServerWithOptions" lang="csharp" />
33
    /// You can also inject a server transport:
34
    /// <list type="bullet">
35
    /// <item><description>an <see cref="IDuplexServerTransport" /> for the ice protocol</description></item>
36
    /// <item><description>an <see cref="IMultiplexedServerTransport" /> for the icerpc protocol</description></item>
37
    /// </list>
38
    ///
39
    /// For example, you can add a QUIC server as follows:
40
    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
41
    /// region="ServerWithQuic" lang="csharp" />
42
    /// If you want to customize the options of the default transport (tcp), you just need to inject
43
    /// an <see cref="IOptions{T}" /> of <see cref="TcpServerTransportOptions" />.
44
    /// </example>
45
    public static IServiceCollection AddIceRpcServer(this IServiceCollection services, IDispatcher dispatcher) =>
46
        services.AddIceRpcServer(optionsName: Options.DefaultName, dispatcher);
×
47

48
    /// <summary>Adds a <see cref="Server" /> to this service collection and configures the dispatch pipeline of this
49
    /// server; you can specify the server's options by injecting an <see cref="IOptions{T}" /> of
50
    /// <see cref="ServerOptions" />.
51
    /// </summary>
52
    /// <param name="services">The service collection to add services to.</param>
53
    /// <param name="configure">The action to configure the dispatch pipeline using an
54
    /// <see cref="IDispatcherBuilder" />.</param>
55
    /// <returns>The service collection.</returns>
56
    /// <remarks>The dispatch pipeline built by this method is not registered in the DI container.</remarks>
57
    /// <example>
58
    /// The following code builds a dispatch pipeline and adds a server with this dispatch pipeline to the service
59
    /// collection.
60
    /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
61
    /// region="ServerWithDispatcherBuilder"
62
    /// lang="csharp" />
63
    /// See also <see cref="AddIceRpcServer(IServiceCollection, IDispatcher)" />.
64
    /// </example>
65
    public static IServiceCollection AddIceRpcServer(
66
        this IServiceCollection services,
67
        Action<IDispatcherBuilder> configure) =>
68
        services.AddIceRpcServer(optionsName: Options.DefaultName, configure);
2✔
69

70
    /// <summary>Adds a <see cref="Server" /> to this service collection; you specify the server's options by injecting
71
    /// an <see cref="IOptions{T}" /> of <see cref="ServerOptions" />.</summary>
72
    /// <param name="services">The service collection to add services to.</param>
73
    /// <returns>The service collection.</returns>
74
    /// <remarks>You need to set a least the dispatcher in the injected options.</remarks>
75
    public static IServiceCollection AddIceRpcServer(this IServiceCollection services) =>
76
        services.AddIceRpcServer(Options.DefaultName);
23✔
77

78
    /// <summary>Adds a <see cref="Server" /> with the specified dispatch pipeline to this service collection; you can
79
    /// specify the server's options by injecting an <see cref="IOptionsMonitor{T}" /> of <see cref="ServerOptions" />
80
    /// named <paramref name="optionsName" />.</summary>
81
    /// <param name="services">The service collection to add services to.</param>
82
    /// <param name="optionsName">The name of the options instance.</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)
97
    {
×
98
        services.AddOptions<ServerOptions>(optionsName).Configure(
×
99
            options => options.ConnectionOptions.Dispatcher = dispatcher);
×
100
        return services.AddIceRpcServer(optionsName);
×
101
    }
×
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.</param>
108
    /// <param name="configure">The action to configure the dispatch pipeline using an
109
    /// <see cref="IDispatcherBuilder" />.</param>
110
    /// <returns>The service collection.</returns>
111
    /// <remarks>The dispatch pipeline built by this method is not registered in the DI container.</remarks>
112
    /// <seealso cref="AddIceRpcServer(IServiceCollection, string, IDispatcher)" />
113
    public static IServiceCollection AddIceRpcServer(
114
        this IServiceCollection services,
115
        string optionsName,
116
        Action<IDispatcherBuilder> configure) =>
117
        services
10✔
118
            .TryAddIceRpcServerTransport()
10✔
119
            .AddSingleton(provider =>
10✔
120
            {
10✔
121
                var dispatcherBuilder = new DispatcherBuilder(provider);
10✔
122
                configure(dispatcherBuilder);
10✔
123

10✔
124
                ServerOptions options = provider.GetRequiredService<IOptionsMonitor<ServerOptions>>().Get(optionsName);
10✔
125
                options.ConnectionOptions.Dispatcher = dispatcherBuilder.Build();
10✔
126

10✔
127
                return new Server(
10✔
128
                    options,
10✔
129
                    provider.GetRequiredService<IDuplexServerTransport>(),
10✔
130
                    provider.GetRequiredService<IMultiplexedServerTransport>(),
10✔
131
                    provider.GetService<ILogger<Server>>());
10✔
132
            });
20✔
133

134
    /// <summary>Adds a <see cref="Server" /> to this service collection; you specify the server's options by injecting
135
    /// an <see cref="IOptionsMonitor{T}" /> of <see cref="ServerOptions" /> named <paramref name="optionsName" />.
136
    /// </summary>
137
    /// <param name="services">The service collection to add services to.</param>
138
    /// <param name="optionsName">The name of the options instance.</param>
139
    /// <returns>The service collection.</returns>
140
    /// <remarks>You need to set a least the dispatcher in the injected options.</remarks>
141
    /// <seealso cref="AddIceRpcServer(IServiceCollection, string, IDispatcher)" />
142
    public static IServiceCollection AddIceRpcServer(this IServiceCollection services, string optionsName) =>
143
        services
23✔
144
            .TryAddIceRpcServerTransport()
23✔
145
            .AddSingleton(provider =>
23✔
146
                new Server(
43✔
147
                    provider.GetRequiredService<IOptionsMonitor<ServerOptions>>().Get(optionsName),
43✔
148
                    provider.GetRequiredService<IDuplexServerTransport>(),
43✔
149
                    provider.GetRequiredService<IMultiplexedServerTransport>(),
43✔
150
                    provider.GetService<ILogger<Server>>()));
43✔
151

152
    private static IServiceCollection TryAddIceRpcServerTransport(this IServiceCollection services)
153
    {
33✔
154
        // The default duplex transport is TCP.
155
        services
33✔
156
           .AddOptions()
33✔
157
           .TryAddSingleton<IDuplexServerTransport>(
33✔
158
               provider => new TcpServerTransport(
33✔
159
                   provider.GetRequiredService<IOptions<TcpServerTransportOptions>>().Value));
33✔
160

161
        services
33✔
162
            .TryAddSingleton<IMultiplexedServerTransport>(
33✔
163
                provider =>
33✔
164
                {
×
165
                    if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsWindows())
×
166
                    {
×
167
                        if (QuicListener.IsSupported)
×
168
                        {
×
169
                            return new QuicServerTransport(
×
170
                                provider.GetRequiredService<IOptions<QuicServerTransportOptions>>().Value);
×
171
                        }
33✔
172
                        throw new NotSupportedException(
×
173
                            "The default QUIC server transport is not available on this system. Please review the Platform Dependencies for QUIC in the .NET documentation.");
×
174
                    }
33✔
175
                    throw new PlatformNotSupportedException(
×
176
                        "The default QUIC server transport is not supported on this platform. You need to register an IMultiplexedServerTransport implementation in the service collection.");
×
177
                });
33✔
178

179
        return services;
33✔
180
    }
33✔
181
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc