@@ -5,20 +5,8 @@ namespace Frank.Channels.DependencyInjection;
55
66public static class ServiceCollectionExtensions
77{
8- internal static bool Contains < TService > ( this IServiceCollection services )
9- {
10- return services . Any ( descriptor => descriptor . ServiceType == typeof ( TService ) ) ;
11- }
12-
13- internal static IServiceCollection AddSingletonIfNotExists < TService , TImplementation > ( this IServiceCollection services ) where TService : class where TImplementation : class , TService
14- {
15- if ( ! services . Contains < TService > ( ) )
16- services . AddSingleton < TService , TImplementation > ( ) ;
17- return services ;
18- }
19-
208 /// <summary>
21- /// Adds a channel of type <typeparamref name="T"/> to the service collection.
9+ /// Adds an unbounded channel of type <typeparamref name="T"/> to the service collection, with default settings .
2210 /// </summary>
2311 /// <remarks>
2412 /// The channel is added as a singleton with its reader and writer as singletons, and injected as follows:
@@ -31,12 +19,97 @@ internal static IServiceCollection AddSingletonIfNotExists<TService, TImplementa
3119 /// <param name="services"></param>
3220 /// <typeparam name="T"></typeparam>
3321 /// <returns></returns>
34- public static IServiceCollection AddChannel < T > ( this IServiceCollection services ) where T : class
22+ public static IServiceCollection AddChannel < T > ( this IServiceCollection services ) where T : class =>
23+ services . AddChannel < T > ( ChannelType . Unbounded , new ChannelSettings ( ) ) ;
24+
25+ /// <summary>
26+ /// Adds a channel of type <typeparamref name="T"/> to the IServiceCollection.
27+ /// </summary>
28+ /// <typeparam name="T">The type of the channel.</typeparam>
29+ /// <param name="services">The IServiceCollection to add the channel to.</param>
30+ /// <param name="channelType">The type of channel to add.</param>
31+ /// <returns>The same instance of the IServiceCollection after the channel has been added.</returns>
32+ /// <remarks>
33+ /// This method adds a channel of type <typeparamref name="T"/> to the IServiceCollection.
34+ /// It allows specifying the channel type (unbounded or bounded) and optional settings for the channel.
35+ /// After the channel is added, it will be available for injection as a singleton instance of Channel{T}.
36+ /// The respective ChannelReader{T} and ChannelWriter{T} instances are also added as singletons.
37+ /// </remarks>
38+ public static IServiceCollection AddChannel < T > ( this IServiceCollection services , ChannelType channelType ) where T : class =>
39+ services . AddChannel < T > ( channelType , new ChannelSettings ( ) ) ;
40+
41+ /// <summary>
42+ /// Adds an unbounded channel of type <typeparamref name="T"/> to the IServiceCollection.
43+ /// </summary>
44+ /// <typeparam name="T">The type of the channel.</typeparam>
45+ /// <param name="services">The IServiceCollection to add the channel to.</param>
46+ /// <returns>The same instance of the IServiceCollection after the channel has been added.</returns>
47+ public static IServiceCollection AddUnboundedChannel < T > ( this IServiceCollection services ) where T : class =>
48+ services . AddChannel < T > ( ChannelType . Unbounded , new ChannelSettings ( ) ) ;
49+
50+ /// <summary>
51+ /// Adds an unbounded channel of type <typeparamref name="T"/> to the IServiceCollection.
52+ /// </summary>
53+ /// <typeparam name="T">The type of the channel.</typeparam>
54+ /// <param name="services">The IServiceCollection to add the channel to.</param>
55+ /// <returns>The same instance of the IServiceCollection after the channel has been added.</returns>
56+ public static IServiceCollection AddUnboundedChannel < T > ( this IServiceCollection services , ChannelSettings settings ) where T : class =>
57+ services . AddChannel < T > ( ChannelType . Unbounded , settings ) ;
58+
59+ /// <summary>
60+ /// Adds a bounded channel of type <typeparamref name="T"/> to the IServiceCollection.
61+ /// </summary>
62+ /// <typeparam name="T">The type of the channel.</typeparam>
63+ /// <param name="services">The IServiceCollection to add the channel to.</param>
64+ /// <returns>The same instance of the IServiceCollection after the channel has been added.</returns>
65+ public static IServiceCollection AddBoundedChannel < T > ( this IServiceCollection services ) where T : class =>
66+ services . AddChannel < T > ( ChannelType . Bounded , new ChannelSettings ( ) ) ;
67+
68+ /// <summary>
69+ /// Adds a bounded channel of type <typeparamref name="T"/> to the IServiceCollection.
70+ /// </summary>
71+ /// <typeparam name="T">The type of the channel.</typeparam>
72+ /// <param name="services">The IServiceCollection to add the channel to.</param>
73+ /// <param name="settings">The settings for the channel.</param>
74+ /// <returns>The same instance of the IServiceCollection after the channel has been added.</returns>
75+ public static IServiceCollection AddBoundedChannel < T > ( this IServiceCollection services , ChannelSettings settings ) where T : class =>
76+ services . AddChannel < T > ( ChannelType . Bounded , settings ) ;
77+
78+ /// <summary>
79+ /// Adds a channel of type <typeparamref name="T"/> to the IServiceCollection.
80+ /// </summary>
81+ /// <typeparam name="T">The type of the channel.</typeparam>
82+ /// <param name="services">The IServiceCollection to add the channel to.</param>
83+ /// <param name="channelType">The type of channel to add.</param>
84+ /// <param name="settings">The settings for the channel.</param>
85+ /// <returns>The same instance of the IServiceCollection after the channel has been added.</returns>
86+ public static IServiceCollection AddChannel < T > ( this IServiceCollection services , ChannelType channelType , ChannelSettings settings ) where T : class =>
87+ services
88+ . ThrowIfContains < Channel < T > > ( )
89+ . AddSingletonIfNotExists < IChannelFactory , ChannelFactory > ( )
90+ . AddSingleton < Channel < T > > ( provider => channelType switch
91+ {
92+ ChannelType . Unbounded => provider . GetRequiredService < IChannelFactory > ( ) . CreateUnboundedChannel < T > ( settings ) ,
93+ ChannelType . Bounded => provider . GetRequiredService < IChannelFactory > ( ) . CreateBoundedChannel < T > ( settings ) ,
94+ _ => throw new ArgumentOutOfRangeException ( nameof ( channelType ) , channelType , null )
95+ } )
96+ . AddSingleton < ChannelReader < T > > ( provider => provider . GetRequiredService < Channel < T > > ( ) . Reader )
97+ . AddSingleton < ChannelWriter < T > > ( provider => provider . GetRequiredService < Channel < T > > ( ) . Writer ) ;
98+
99+ private static IServiceCollection AddSingletonIfNotExists < TService , TImplementation > ( this IServiceCollection services ) where TService : class where TImplementation : class , TService
35100 {
36- services . AddSingletonIfNotExists < IChannelFactory , ChannelFactory > ( ) ;
37- services . AddSingleton < Channel < T > > ( provider => provider . GetRequiredService < IChannelFactory > ( ) . CreateChannel < T > ( ) ) ;
38- services . AddSingleton < ChannelReader < T > > ( provider => provider . GetRequiredService < Channel < T > > ( ) . Reader ) ;
39- services . AddSingleton < ChannelWriter < T > > ( provider => provider . GetRequiredService < Channel < T > > ( ) . Writer ) ;
101+ if ( ! services . Contains < TService > ( ) )
102+ services . AddSingleton < TService , TImplementation > ( ) ;
40103 return services ;
41104 }
105+
106+ private static IServiceCollection ThrowIfContains < TService > ( this IServiceCollection services ) where TService : class
107+ {
108+ if ( services . Contains < TService > ( ) )
109+ throw new InvalidOperationException ( $ "Service of type { typeof ( TService ) . Name } already exists in the service collection.") ;
110+ return services ;
111+ }
112+
113+ private static bool Contains < TService > ( this IServiceCollection services )
114+ => services . Any ( descriptor => descriptor . ServiceType == typeof ( TService ) ) ;
42115}
0 commit comments