| | 1 | | using System.Threading.Channels; |
| | 2 | |
|
| | 3 | | using Microsoft.Extensions.DependencyInjection.Extensions; |
| | 4 | |
|
| | 5 | | using mkmrk.Channels; |
| | 6 | |
|
| | 7 | | namespace Microsoft.Extensions.DependencyInjection; |
| | 8 | |
|
| | 9 | | /// <summary> |
| | 10 | | /// Extensions for <see cref="IServiceCollection"/> to add the required services for <see cref="BroadcastChannel{TData,T |
| | 11 | | /// </summary> |
| | 12 | | public static class BroadcastChannelServiceCollectionExtensions { |
| | 13 | | /// <summary> |
| | 14 | | /// Add the required services for <see cref="BroadcastChannel{TData,TResponse}"/>. |
| | 15 | | /// </summary> |
| | 16 | | /// <remarks> |
| | 17 | | /// <list type="deflist"> |
| | 18 | | /// <item><term><see cref="BroadcastChannel{TData, TResponse}"/></term><description>will be added as a Singleton</de |
| | 19 | | /// <item><term><see cref="BroadcastChannelWriter{TData, TResponse}"/></term><description>will be added as a Singlet |
| | 20 | | /// <item><term><see cref="BroadcastChannelReader{TData, TResponse}"/></term><description>will be added as Transient |
| | 21 | | /// </list> |
| | 22 | | /// A single writer should be used throughout the life of an application. When readers are disposed of, the object w |
| | 23 | | /// There are some cases where a Singleton reader might be desirable, such as for long lived <c>IHostedService</c>, |
| | 24 | | /// but this will have to be added manually using the full <see cref="BroadcastChannel{TData, TResponse}"/> form rat |
| | 25 | | /// </remarks> |
| 2 | 26 | | public static IServiceCollection AddBroadcastChannel<TData, TResponse>( this IServiceCollection services ) where TRe |
| 2 | 27 | | services.TryAddSingleton<IBroadcastChannel<TData, TResponse>, BroadcastChannel<TData, TResponse>>(); |
| 2 | 28 | | services.TryAddSingleton<IBroadcastChannelWriter<TData, TResponse>, BroadcastChannelWriter<TData, TResponse>>(); |
| 2 | 29 | | services.TryAddTransient<IBroadcastChannelReader<TData, TResponse>, BroadcastChannelReader<TData, TResponse>>(); |
| | 30 | | /* |
| | 31 | | * AddSingleton instead of TryAddSingleton here because there could be more than one IBroadcastChannelWriter<TDa |
| | 32 | | * so keep them all and let the user determine which they want. |
| | 33 | | */ |
| 2 | 34 | | services.AddSingleton<IBroadcastChannel<TData>>( sp => { |
| 2 | 35 | | IBroadcastChannel<TData> broadcastChannel = sp.GetRequiredService<IBroadcastChannel<TData, TResponse>>() as |
| 2 | 36 | | ?? ThrowHelper.ThrowInvalidCastException<IBroadcastChannel<TData |
| 2 | 37 | | return broadcastChannel; |
| 2 | 38 | | } ); |
| 2 | 39 | | services.AddSingleton<IBroadcastChannelWriter<TData>>( sp => { |
| 2 | 40 | | IBroadcastChannelWriter<TData, TResponse> broadcastChannelWriter = sp.GetRequiredService<IBroadcastChannelWr |
| 2 | 41 | | return broadcastChannelWriter; |
| 2 | 42 | | } ); |
| 2 | 43 | | services.AddTransient<IBroadcastChannelReader<TData>>( sp => { |
| 2 | 44 | | IBroadcastChannelReader<TData, TResponse> broadcastChannelReader = sp.GetRequiredService<IBroadcastChannelWr |
| 2 | 45 | | return broadcastChannelReader; |
| 2 | 46 | | } ); |
| | 47 | |
|
| | 48 | | // reader sources |
| 2 | 49 | | services.TryAddTransient<BroadcastChannelReaderSource<TData, TResponse>>(); // concrete so that the implicit con |
| 2 | 50 | | services.TryAddTransient<IBroadcastChannelReaderSource<TData, TResponse>, BroadcastChannelReaderSource<TData, TR |
| 2 | 51 | | services.TryAddTransient<IBroadcastChannelReaderSource<TData>, BroadcastChannelReaderSource<TData, TResponse>>() |
| 2 | 52 | | services.TryAddTransient<IBroadcastChannelAddReaderProvider<TData>, BroadcastChannelReaderSource<TData, TRespons |
| | 53 | |
|
| | 54 | |
|
| 2 | 55 | | return services; |
| 2 | 56 | | } |
| | 57 | |
|
| | 58 | | /// <summary> |
| | 59 | | /// Add the required services for <b><i>any</i></b> requested BroadcastChannel resource. |
| | 60 | | /// </summary> |
| | 61 | | /// <remarks> |
| | 62 | | /// It is important to note that requesting <c>BroadcastChannel<TData></c> will |
| | 63 | | /// not result in the same instance as requesting <c>BroadcastChannel<TData,IBroadcastChannelResponse></c>. |
| | 64 | | /// <br/> |
| | 65 | | /// For Example: |
| | 66 | | /// <code> |
| | 67 | | /// var writerResponseTypeSpecified = _host.Services.GetRequiredService<BroadcastChannelReader<ChannelMessageS |
| | 68 | | /// var readerNoResponseTypeSpecified = _host.Services.GetRequiredService<BroadcastChannelReader<ChannelMessag |
| | 69 | | /// Console.WriteLine(writerResponseTypeSpecified.ReaderCount); // 0 |
| | 70 | | /// var writerNoResponseTypeSpecified = _host.Services.GetRequiredService<BroadcastChannelReader<ChannelMessag |
| | 71 | | /// Console.WriteLine(writerNoResponseTypeSpecified.ReaderCount); // 1 |
| | 72 | | /// </code> |
| | 73 | | /// </remarks> |
| | 74 | | /// <inheritdoc cref="AddBroadcastChannel{TData,TResponse}" path="/remarks" /> |
| 2 | 75 | | public static IServiceCollection AddBroadcastChannels( this IServiceCollection services ) { |
| | 76 | | // Data and response generic type parameters |
| 2 | 77 | | services.TryAddSingleton( typeof(IBroadcastChannel<>), typeof(BroadcastChannel<>) ); |
| 2 | 78 | | services.TryAddSingleton( typeof(IBroadcastChannelWriter<>), typeof(BroadcastChannelWriter<>) ); |
| 2 | 79 | | services.TryAddTransient( typeof(IBroadcastChannelReader<>), typeof(BroadcastChannelReader<>) ); |
| 2 | 80 | | services.TryAddTransient( typeof(IBroadcastChannelReaderSource<>), typeof(BroadcastChannelReaderSource<>) ); |
| 2 | 81 | | services.TryAddTransient( typeof(IBroadcastChannelAddReaderProvider<>), typeof(BroadcastChannelReaderSource<>) ) |
| | 82 | |
|
| | 83 | |
|
| | 84 | | // ChannelMux |
| 2 | 85 | | services.TryAddTransient( typeof(ChannelMux<,>) ); |
| 2 | 86 | | services.TryAddTransient( typeof(ChannelMux<,,>) ); |
| 2 | 87 | | services.TryAddTransient( typeof(ChannelMux<,,,>) ); |
| 2 | 88 | | services.TryAddTransient( typeof(ChannelMux<,,,,>) ); |
| 2 | 89 | | services.TryAddTransient( typeof(ChannelMux<,,,,,>) ); |
| 2 | 90 | | services.TryAddTransient( typeof(ChannelMux<,,,,,,>) ); |
| 2 | 91 | | services.TryAddTransient( typeof(ChannelMux<,,,,,,,>) ); |
| 2 | 92 | | return services; |
| 2 | 93 | | } |
| | 94 | |
|
| | 95 | | /// <summary> |
| | 96 | | /// Add the required services for <b><i>any</i></b> requested <see cref="BroadcastChannel{TData,TResponse}"/> |
| | 97 | | /// replacing any requests for <see cref="Channel{T}"/>, <see cref="ChannelWriter{T}"/>, and <see cref="ChannelReade |
| | 98 | | /// </summary> |
| | 99 | | /// <inheritdoc cref="AddBroadcastChannel{TData,TResponse}" path="/remarks" /> |
| 0 | 100 | | public static IServiceCollection AddBroadcastChannelsAsChannel( this IServiceCollection services ) { |
| 0 | 101 | | services.TryAddSingleton( typeof(Channel<>), typeof(BroadcastChannel<>) ); |
| 0 | 102 | | services.TryAddSingleton( typeof(ChannelWriter<>), typeof(BroadcastChannelWriter<>) ); |
| 0 | 103 | | services.TryAddTransient( typeof(ChannelReader<>), typeof(BroadcastChannelReader<>) ); |
| 0 | 104 | | return services; |
| 0 | 105 | | } |
| | 106 | | } |