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

icerpc / icerpc-csharp / 20824049881

08 Jan 2026 04:31PM UTC coverage: 83.533% (-0.08%) from 83.616%
20824049881

Pull #4214

github

web-flow
Merge 4faeebbc7 into 0c66ff81c
Pull Request #4214: Fix DI default multiplexed transport, tests, and templates

12063 of 14441 relevant lines covered (83.53%)

2994.28 hits per line

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

75.93
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.Slic;
7
using IceRpc.Transports.Tcp;
8
using Microsoft.Extensions.DependencyInjection;
9
using Microsoft.Extensions.DependencyInjection.Extensions;
10
using Microsoft.Extensions.Logging;
11
using Microsoft.Extensions.Options;
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
        // The default multiplexed transport is QUIC on most platforms.
162
        if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsWindows())
33✔
163
        {
33✔
164
#pragma warning disable CA1416 // Validate platform compatibility
165
            services
33✔
166
                .TryAddSingleton<IMultiplexedServerTransport>(
33✔
167
                    provider => new QuicServerTransport(
33✔
168
                        provider.GetRequiredService<IOptions<QuicServerTransportOptions>>().Value));
33✔
169
#pragma warning restore CA1416 // Validate platform compatibility
170
        }
33✔
171
        else
172
        {
×
173
            // Use Slic over TCP on other platforms.
174
            services
×
175
                .TryAddSingleton<IMultiplexedServerTransport>(
×
176
                    provider => new SlicServerTransport(
×
177
                        provider.GetRequiredService<IOptions<SlicTransportOptions>>().Value,
×
178
                        provider.GetRequiredService<IDuplexServerTransport>()));
×
179
        }
×
180

181
        return services;
33✔
182
    }
33✔
183
}
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