66using System . Diagnostics . CodeAnalysis ;
77using System . Linq ;
88using Microsoft . Extensions . DependencyInjection ;
9+ using Microsoft . Shared . DiagnosticIds ;
910using Microsoft . Shared . Diagnostics ;
1011
1112namespace Microsoft . Extensions . DependencyInjection ;
1213
1314/// <summary>
1415/// Extension methods for automatically activating singletons after application starts.
1516/// </summary>
16- public static class AutoActivationExtensions
17+ public static partial class AutoActivationExtensions
1718{
1819 /// <summary>
1920 /// Enforces singleton activation at startup time rather then at runtime.
2021 /// </summary>
21- /// <typeparam name="TService">The type of the service to add .</typeparam>
22+ /// <typeparam name="TService">The type of the service to activate .</typeparam>
2223 /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
2324 /// <returns>A reference to this instance after the operation has completed.</returns>
2425 public static IServiceCollection Activate < TService > ( this IServiceCollection services )
2526 where TService : class
2627 {
2728 _ = Throw . IfNull ( services ) ;
2829
29- _ = services . AddHostedService < AutoActivationHostedService > ( )
30- . AddOptions < AutoActivatorOptions > ( )
31- . Configure ( ao =>
32- {
33- var constructed = typeof ( IEnumerable < TService > ) ;
34- if ( ao . AutoActivators . Contains ( constructed ) )
35- {
36- return ;
37- }
38-
39- if ( ao . AutoActivators . Remove ( typeof ( TService ) ) )
40- {
41- _ = ao . AutoActivators . Add ( constructed ) ;
42- return ;
43- }
44-
45- _ = ao . AutoActivators . Add ( typeof ( TService ) ) ;
46- } ) ;
30+ _ = services
31+ . AddHostedService < AutoActivationHostedService > ( )
32+ . AddOptions < AutoActivatorOptions > ( )
33+ . Configure ( ao =>
34+ {
35+ var constructed = typeof ( IEnumerable < TService > ) ;
36+ if ( ao . AutoActivators . Contains ( constructed ) )
37+ {
38+ return ;
39+ }
40+
41+ if ( ao . AutoActivators . Remove ( typeof ( TService ) ) )
42+ {
43+ _ = ao . AutoActivators . Add ( constructed ) ;
44+ return ;
45+ }
46+
47+ _ = ao . AutoActivators . Add ( typeof ( TService ) ) ;
48+ } ) ;
49+
50+ return services ;
51+ }
52+
53+ /// <summary>
54+ /// Enforces singleton activation at startup time rather then at runtime.
55+ /// </summary>
56+ /// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
57+ /// <param name="serviceType">The type of the service to activate.</param>
58+ /// <returns>A reference to this instance after the operation has completed.</returns>
59+ [ Experimental ( diagnosticId : Experiments . AutoActivation , UrlFormat = Experiments . UrlFormat ) ]
60+ [ UnconditionalSuppressMessage (
61+ "Trimming" ,
62+ "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code" ,
63+ Justification = "Addressed with [DynamicallyAccessedMembers]" ) ]
64+ public static IServiceCollection Activate ( this IServiceCollection services , [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ] Type serviceType )
65+ {
66+ _ = Throw . IfNull ( services ) ;
67+ _ = Throw . IfNull ( serviceType ) ;
68+
69+ _ = services
70+ . AddHostedService < AutoActivationHostedService > ( )
71+ . AddOptions < AutoActivatorOptions > ( )
72+ . Configure ( ao =>
73+ {
74+ var constructed = typeof ( IEnumerable < > ) . MakeGenericType ( serviceType ) ;
75+ if ( ao . AutoActivators . Contains ( constructed ) )
76+ {
77+ return ;
78+ }
79+
80+ if ( ao . AutoActivators . Remove ( serviceType ) )
81+ {
82+ _ = ao . AutoActivators . Add ( constructed ) ;
83+ return ;
84+ }
85+
86+ _ = ao . AutoActivators . Add ( serviceType ) ;
87+ } ) ;
4788
4889 return services ;
4990 }
@@ -270,38 +311,10 @@ public static void TryAddActivatedSingleton<TService>(this IServiceCollection se
270311 services . TryAddAndActivate < TService > ( ServiceDescriptor . Singleton < TService > ( implementationFactory ) ) ;
271312 }
272313
273- [ UnconditionalSuppressMessage (
274- "Trimming" ,
275- "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code" ,
276- Justification = "Addressed with [DynamicallyAccessedMembers]" ) ]
277- internal static IServiceCollection Activate ( this IServiceCollection services , [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ] Type serviceType )
278- {
279- _ = services . AddHostedService < AutoActivationHostedService > ( )
280- . AddOptions < AutoActivatorOptions > ( )
281- . Configure ( ao =>
282- {
283- var constructed = typeof ( IEnumerable < > ) . MakeGenericType ( serviceType ) ;
284- if ( ao . AutoActivators . Contains ( constructed ) )
285- {
286- return ;
287- }
288-
289- if ( ao . AutoActivators . Remove ( serviceType ) )
290- {
291- _ = ao . AutoActivators . Add ( constructed ) ;
292- return ;
293- }
294-
295- _ = ao . AutoActivators . Add ( serviceType ) ;
296- } ) ;
297-
298- return services ;
299- }
300-
301314 private static void TryAddAndActivate < TService > ( this IServiceCollection services , ServiceDescriptor descriptor )
302315 where TService : class
303316 {
304- if ( services . Any ( d => d . ServiceType == descriptor . ServiceType ) )
317+ if ( services . Any ( d => d . ServiceType == descriptor . ServiceType && d . ServiceKey == descriptor . ServiceKey ) )
305318 {
306319 return ;
307320 }
@@ -312,7 +325,7 @@ private static void TryAddAndActivate<TService>(this IServiceCollection services
312325
313326 private static void TryAddAndActivate ( this IServiceCollection services , ServiceDescriptor descriptor )
314327 {
315- if ( services . Any ( d => d . ServiceType == descriptor . ServiceType ) )
328+ if ( services . Any ( d => d . ServiceType == descriptor . ServiceType && d . ServiceKey == descriptor . ServiceKey ) )
316329 {
317330 return ;
318331 }
0 commit comments