| | 1 | | // Copyright (c) ZeroC, Inc. |
| | 2 | |
|
| | 3 | | using IceRpc.Extensions.DependencyInjection.Internal; |
| | 4 | | using IceRpc.Transports; |
| | 5 | | using IceRpc.Transports.Slic; |
| | 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 | |
|
| | 12 | | namespace IceRpc.Extensions.DependencyInjection; |
| | 13 | |
|
| | 14 | | /// <summary>Provides extension methods for <see cref="IServiceCollection" /> to add a <see cref="Server" />.</summary> |
| | 15 | | public 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, the default multiplexed |
| | 28 | | /// transport (tcp) and <c>null</c> for its authentication options (so no TLS). If you want to customize this |
| | 29 | | /// server, add an <see cref="IOptions{T}" /> of <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 QUIC server as follows: |
| | 39 | | /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs" |
| | 40 | | /// region="ServerWithQuic" lang="csharp" /> |
| | 41 | | /// If you want to customize the options of the default transport (tcp), you just need to inject |
| | 42 | | /// an <see cref="IOptions{T}" /> of <see cref="TcpServerTransportOptions" />. |
| | 43 | | /// </example> |
| | 44 | | public static IServiceCollection AddIceRpcServer(this IServiceCollection services, IDispatcher dispatcher) => |
| 0 | 45 | | 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) => |
| 2 | 67 | | 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) => |
| 40 | 75 | | 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.</param> |
| | 82 | | /// <param name="dispatcher">The dispatch pipeline of the server.</param> |
| | 83 | | /// <returns>The service collection.</returns> |
| | 84 | | /// <example> |
| | 85 | | /// A server application may need to host multiple <see cref="Server" /> instances, each with its own options. A |
| | 86 | | /// typical example is when you want to accept requests from clients over both the icerpc protocol and the ice |
| | 87 | | /// protocol. This overload allows you to add two (or more) server singletons, each with its own options: |
| | 88 | | /// <code source="../../docfx/examples/IceRpc.Extensions.DependencyInjection.Examples/AddIceRpcServerExamples.cs" |
| | 89 | | /// region="ServerWithNamedOptions" lang="csharp" /> |
| | 90 | | /// See also <see cref="AddIceRpcServer(IServiceCollection, IDispatcher)" />. |
| | 91 | | /// </example> |
| | 92 | | public static IServiceCollection AddIceRpcServer( |
| | 93 | | this IServiceCollection services, |
| | 94 | | string optionsName, |
| | 95 | | IDispatcher dispatcher) |
| 0 | 96 | | { |
| 0 | 97 | | services.AddOptions<ServerOptions>(optionsName).Configure( |
| 0 | 98 | | options => options.ConnectionOptions.Dispatcher = dispatcher); |
| 0 | 99 | | return services.AddIceRpcServer(optionsName); |
| 0 | 100 | | } |
| | 101 | |
|
| | 102 | | /// <summary>Adds a <see cref="Server" /> to this service collection and configures the dispatch pipeline of this |
| | 103 | | /// server; you can specify the server's options by injecting an <see cref="IOptionsMonitor{T}" /> of |
| | 104 | | /// <see cref="ServerOptions" /> named <paramref name="optionsName" />.</summary> |
| | 105 | | /// <param name="services">The service collection to add services to.</param> |
| | 106 | | /// <param name="optionsName">The name of the options instance.</param> |
| | 107 | | /// <param name="configure">The action to configure the dispatch pipeline using an |
| | 108 | | /// <see cref="IDispatcherBuilder" />.</param> |
| | 109 | | /// <returns>The service collection.</returns> |
| | 110 | | /// <remarks>The dispatch pipeline built by this method is not registered in the DI container.</remarks> |
| | 111 | | /// <seealso cref="AddIceRpcServer(IServiceCollection, string, IDispatcher)" /> |
| | 112 | | public static IServiceCollection AddIceRpcServer( |
| | 113 | | this IServiceCollection services, |
| | 114 | | string optionsName, |
| | 115 | | Action<IDispatcherBuilder> configure) => |
| 10 | 116 | | services |
| 10 | 117 | | .TryAddIceRpcServerTransport() |
| 10 | 118 | | .AddSingleton(provider => |
| 10 | 119 | | { |
| 10 | 120 | | var dispatcherBuilder = new DispatcherBuilder(provider); |
| 10 | 121 | | configure(dispatcherBuilder); |
| 10 | 122 | |
|
| 10 | 123 | | ServerOptions options = provider.GetRequiredService<IOptionsMonitor<ServerOptions>>().Get(optionsName); |
| 10 | 124 | | options.ConnectionOptions.Dispatcher = dispatcherBuilder.Build(); |
| 10 | 125 | |
|
| 10 | 126 | | return new Server( |
| 10 | 127 | | options, |
| 10 | 128 | | provider.GetRequiredService<IDuplexServerTransport>(), |
| 10 | 129 | | provider.GetRequiredService<IMultiplexedServerTransport>(), |
| 10 | 130 | | provider.GetService<ILogger<Server>>()); |
| 20 | 131 | | }); |
| | 132 | |
|
| | 133 | | /// <summary>Adds a <see cref="Server" /> to this service collection; you specify the server's options by injecting |
| | 134 | | /// an <see cref="IOptionsMonitor{T}" /> of <see cref="ServerOptions" /> named <paramref name="optionsName" />. |
| | 135 | | /// </summary> |
| | 136 | | /// <param name="services">The service collection to add services to.</param> |
| | 137 | | /// <param name="optionsName">The name of the options instance.</param> |
| | 138 | | /// <returns>The service collection.</returns> |
| | 139 | | /// <remarks>You need to set a least the dispatcher in the injected options.</remarks> |
| | 140 | | /// <seealso cref="AddIceRpcServer(IServiceCollection, string, IDispatcher)" /> |
| | 141 | | public static IServiceCollection AddIceRpcServer(this IServiceCollection services, string optionsName) => |
| 40 | 142 | | services |
| 40 | 143 | | .TryAddIceRpcServerTransport() |
| 40 | 144 | | .AddSingleton(provider => |
| 76 | 145 | | new Server( |
| 76 | 146 | | provider.GetRequiredService<IOptionsMonitor<ServerOptions>>().Get(optionsName), |
| 76 | 147 | | provider.GetRequiredService<IDuplexServerTransport>(), |
| 76 | 148 | | provider.GetRequiredService<IMultiplexedServerTransport>(), |
| 76 | 149 | | provider.GetService<ILogger<Server>>())); |
| | 150 | |
|
| | 151 | | private static IServiceCollection TryAddIceRpcServerTransport(this IServiceCollection services) |
| 50 | 152 | | { |
| 50 | 153 | | services |
| 50 | 154 | | .AddOptions() |
| 50 | 155 | | .TryAddSingleton<IDuplexServerTransport>( |
| 50 | 156 | | provider => new TcpServerTransport( |
| 50 | 157 | | provider.GetRequiredService<IOptions<TcpServerTransportOptions>>().Value)); |
| | 158 | |
|
| 50 | 159 | | services |
| 50 | 160 | | .TryAddSingleton<IMultiplexedServerTransport>( |
| 92 | 161 | | provider => new SlicServerTransport( |
| 92 | 162 | | provider.GetRequiredService<IOptions<SlicTransportOptions>>().Value, |
| 92 | 163 | | provider.GetRequiredService<IDuplexServerTransport>())); |
| | 164 | |
|
| 50 | 165 | | return services; |
| 50 | 166 | | } |
| | 167 | | } |