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

icerpc / icerpc-csharp / 20870171951

10 Jan 2026 01:03AM UTC coverage: 83.304% (-0.1%) from 83.399%
20870171951

Pull #4221

github

web-flow
Merge fe4f556d8 into f39e9819d
Pull Request #4221: Use new C#14 extension block syntax

12030 of 14441 relevant lines covered (83.3%)

2957.05 hits per line

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

67.8
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>Extension methods for <see cref="IServiceCollection" />.</summary>
19
    /// <param name="services">The service collection to add services to.</param>
20
    extension(IServiceCollection services)
21
    {
22
        /// <summary>Adds a <see cref="Server" /> with the specified dispatch pipeline to this service
23
        /// collection; you can specify the server's options by injecting an <see cref="IOptions{T}" /> of
24
        /// <see cref="ServerOptions" />.</summary>
25
        /// <param name="dispatcher">The dispatch pipeline.</param>
26
        /// <returns>The service collection.</returns>
27
        /// <example>
28
        /// The following code adds a Server singleton to the service collection.
29
        /// <code
30
        ///     source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
31
        ///     region="DefaultServer"
32
        ///     lang="csharp" />
33
        /// The resulting singleton is a default server: it uses the default server address and the default
34
        /// multiplexed transport (QUIC). If you want to customize this server, add an <see cref="IOptions{T}" /> of
35
        /// <see cref="ServerOptions" /> to your DI container:
36
        /// <code
37
        ///     source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
38
        ///     region="ServerWithOptions"
39
        ///     lang="csharp" />
40
        /// You can also inject a server transport:
41
        /// <list type="bullet">
42
        /// <item><description>an <see cref="IDuplexServerTransport" /> for the ice protocol</description>
43
        /// </item>
44
        /// <item><description>an <see cref="IMultiplexedServerTransport" /> for the icerpc protocol</description>
45
        /// </item>
46
        /// </list>
47
        ///
48
        /// For example, you can add a Slic over TCP server as follows:
49
        /// <code
50
        ///     source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
51
        ///     region="ServerWithSlic"
52
        ///     lang="csharp" />
53
        /// If you want to customize the options of the default transport (QUIC), you just need to inject
54
        /// an <see cref="IOptions{T}" /> of <see cref="QuicServerTransportOptions" />.
55
        /// </example>
56
        public IServiceCollection AddIceRpcServer(IDispatcher dispatcher) =>
57
            services.AddIceRpcServer(optionsName: Options.DefaultName, dispatcher);
×
58

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

79
        /// <summary>Adds a <see cref="Server" /> to this service collection; you specify the server's options by
80
        /// injecting an <see cref="IOptions{T}" /> of <see cref="ServerOptions" />.</summary>
81
        /// <returns>The service collection.</returns>
82
        /// <remarks>You need to set a least the dispatcher in the injected options.</remarks>
83
        public IServiceCollection AddIceRpcServer() =>
84
            services.AddIceRpcServer(Options.DefaultName);
23✔
85

86
        /// <summary>Adds a <see cref="Server" /> with the specified dispatch pipeline to this service collection;
87
        /// you can specify the server's options by injecting an <see cref="IOptionsMonitor{T}" /> of
88
        /// <see cref="ServerOptions" /> named <paramref name="optionsName" />.</summary>
89
        /// <param name="optionsName">The name of the options instance.</param>
90
        /// <param name="dispatcher">The dispatch pipeline of the server.</param>
91
        /// <returns>The service collection.</returns>
92
        /// <example>
93
        /// A server application may need to host multiple <see cref="Server" /> instances, each with its own options.
94
        /// A typical example is when you want to accept requests from clients over both the icerpc protocol and the
95
        /// ice protocol. This overload allows you to add two (or more) server singletons, each with its own options:
96
        /// <code
97
        ///     source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs"
98
        ///     region="ServerWithNamedOptions"
99
        ///     lang="csharp" />
100
        /// See also
101
        /// <see cref="ServerServiceCollectionExtensions.extension(IServiceCollection).AddIceRpcServer(IDispatcher)" />.
102
        /// </example>
103
        public IServiceCollection AddIceRpcServer(
104
            string optionsName,
105
            IDispatcher dispatcher)
106
        {
×
107
            services.AddOptions<ServerOptions>(optionsName).Configure(
×
108
                options => options.ConnectionOptions.Dispatcher = dispatcher);
×
109
            return services.AddIceRpcServer(optionsName);
×
110
        }
111

112
        /// <summary>Adds a <see cref="Server" /> to this service collection and configures the dispatch pipeline of
113
        /// this server; you can specify the server's options by injecting an <see cref="IOptionsMonitor{T}" /> of
114
        /// <see cref="ServerOptions" /> named <paramref name="optionsName" />.</summary>
115
        /// <param name="optionsName">The name of the options instance.</param>
116
        /// <param name="configure">The action to configure the dispatch pipeline using an
117
        /// <see cref="IDispatcherBuilder" />.</param>
118
        /// <returns>The service collection.</returns>
119
        /// <remarks>The dispatch pipeline built by this method is not registered in the DI container.</remarks>
120
        /// <seealso
121
        ///     cref="ServerServiceCollectionExtensions.extension(IServiceCollection).AddIceRpcServer(string, IDispatcher)" />
122
        public IServiceCollection AddIceRpcServer(
123
            string optionsName,
124
            Action<IDispatcherBuilder> configure) =>
125
            services
10✔
126
                .TryAddIceRpcServerTransport()
10✔
127
                .AddSingleton(provider =>
10✔
128
                {
10✔
129
                    var dispatcherBuilder = new DispatcherBuilder(provider);
10✔
130
                    configure(dispatcherBuilder);
10✔
131

10✔
132
                    ServerOptions options =
10✔
133
                        provider.GetRequiredService<IOptionsMonitor<ServerOptions>>().Get(optionsName);
10✔
134
                    options.ConnectionOptions.Dispatcher = dispatcherBuilder.Build();
10✔
135

10✔
136
                    return new Server(
10✔
137
                        options,
10✔
138
                        provider.GetRequiredService<IDuplexServerTransport>(),
10✔
139
                        provider.GetRequiredService<IMultiplexedServerTransport>(),
10✔
140
                        provider.GetService<ILogger<Server>>());
10✔
141
                });
20✔
142

143
        /// <summary>Adds a <see cref="Server" /> to this service collection; you specify the server's options by
144
        /// injecting an <see cref="IOptionsMonitor{T}" /> of <see cref="ServerOptions" /> named
145
        /// <paramref name="optionsName" />.</summary>
146
        /// <param name="optionsName">The name of the options instance.</param>
147
        /// <returns>The service collection.</returns>
148
        /// <remarks>You need to set a least the dispatcher in the injected options.</remarks>
149
        /// <seealso
150
        ///     cref="ServerServiceCollectionExtensions.extension(IServiceCollection).AddIceRpcServer(string, IDispatcher)" />
151
        public IServiceCollection AddIceRpcServer(string optionsName) =>
152
            services
23✔
153
                .TryAddIceRpcServerTransport()
23✔
154
                .AddSingleton(provider =>
23✔
155
                    new Server(
43✔
156
                        provider.GetRequiredService<IOptionsMonitor<ServerOptions>>().Get(optionsName),
43✔
157
                        provider.GetRequiredService<IDuplexServerTransport>(),
43✔
158
                        provider.GetRequiredService<IMultiplexedServerTransport>(),
43✔
159
                        provider.GetService<ILogger<Server>>()));
43✔
160

161
        private IServiceCollection TryAddIceRpcServerTransport()
162
        {
33✔
163
            // The default duplex transport is TCP.
164
            services
33✔
165
               .AddOptions()
33✔
166
               .TryAddSingleton<IDuplexServerTransport>(
33✔
167
                   provider => new TcpServerTransport(
33✔
168
                       provider.GetRequiredService<IOptions<TcpServerTransportOptions>>().Value));
33✔
169

170
            services
33✔
171
                .TryAddSingleton<IMultiplexedServerTransport>(
33✔
172
                    provider =>
33✔
173
                    {
×
174
                        if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsWindows())
×
175
                        {
×
176
                            if (QuicListener.IsSupported)
×
177
                            {
×
178
                                return new QuicServerTransport(
×
179
                                    provider.GetRequiredService<IOptions<QuicServerTransportOptions>>().Value);
×
180
                            }
33✔
181
                            throw new NotSupportedException(
×
182
                                "The default QUIC server transport is not available on this system. " +
×
183
                                "Please review the Platform Dependencies for QUIC in the .NET documentation.");
×
184
                        }
33✔
185
                        throw new PlatformNotSupportedException(
×
186
                            "The default QUIC server transport is not supported on this platform. " +
×
187
                            "You need to register an IMultiplexedServerTransport implementation " +
×
188
                            "in the service collection.");
×
189
                    });
33✔
190

191
            return services;
33✔
192
        }
193
    }
194
}
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