@@ -22,15 +22,42 @@ public static class SimpleInjectorAddOptionsAspNetCoreExtensions
22
22
/// additional integration options to be applied. These basic integrations includes wrapping each web
23
23
/// request in an <see cref="AsyncScopedLifestyle"/> scope and making the nessesary changes that make
24
24
/// it possible for enabling the injection of framework components in Simple Injector-constructed
25
- /// components when
25
+ /// components when
26
26
/// <see cref="SimpleInjectorServiceCollectionExtensions.UseSimpleInjector(IServiceProvider, Container)"/>
27
- /// is called.
27
+ /// is called. This method uses the default <see cref="ServiceScopeReuseBehavior"/>, which is
28
+ /// <see cref="ServiceScopeReuseBehavior.OnePerRequest"/>. This means that within a single web request, the same
29
+ /// <see cref="IServiceScope"/> instance will be used, irregardless of the number of Simple Injector
30
+ /// <see cref="Scope"/> instances you create. Outside the context of a web request, the ASP.NET Core
31
+ /// integration falls back to the default behavior specified by the
32
+ /// <see cref="SimpleInjectorAddOptions.ServiceProviderAccessor"/>. By default, a new
33
+ /// <see cref="IServiceScope"/> instance will be created per Simple Injector <see cref="Scope"/>.
28
34
/// </summary>
29
35
/// <param name="options">The options to which the integration should be applied.</param>
30
36
/// <returns>A new <see cref="SimpleInjectorAspNetCoreBuilder"/> instance that allows additional
31
37
/// configurations to be made.</returns>
32
38
/// <exception cref="ArgumentNullException">Thrown when <paramref name="options"/> is null.</exception>
33
39
public static SimpleInjectorAspNetCoreBuilder AddAspNetCore ( this SimpleInjectorAddOptions options )
40
+ {
41
+ return AddAspNetCore ( options , ServiceScopeReuseBehavior . OnePerRequest ) ;
42
+ }
43
+
44
+ /// <summary>
45
+ /// Adds basic Simple Injector integration for ASP.NET Core and returns a builder object that allow
46
+ /// additional integration options to be applied. These basic integrations includes wrapping each web
47
+ /// request in an <see cref="AsyncScopedLifestyle"/> scope and making the nessesary changes that make
48
+ /// it possible for enabling the injection of framework components in Simple Injector-constructed
49
+ /// components when
50
+ /// <see cref="SimpleInjectorServiceCollectionExtensions.UseSimpleInjector(IServiceProvider, Container)"/>
51
+ /// is called.
52
+ /// </summary>
53
+ /// <param name="options">The options to which the integration should be applied.</param>
54
+ /// <param name="serviceScopeBehavior">Defines in which way Simple Injector should use and reuse the ASP.NET
55
+ /// Core <see cref="IServiceScope"/>, which is used to resolve cross-wired dependencies from.</param>
56
+ /// <returns>A new <see cref="SimpleInjectorAspNetCoreBuilder"/> instance that allows additional
57
+ /// configurations to be made.</returns>
58
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="options"/> is null.</exception>
59
+ public static SimpleInjectorAspNetCoreBuilder AddAspNetCore (
60
+ this SimpleInjectorAddOptions options , ServiceScopeReuseBehavior serviceScopeBehavior )
34
61
{
35
62
if ( options is null )
36
63
{
@@ -44,15 +71,41 @@ public static SimpleInjectorAspNetCoreBuilder AddAspNetCore(this SimpleInjectorA
44
71
// Add the IHttpContextAccessor to allow Simple Injector cross wiring to work in ASP.NET Core.
45
72
services . TryAddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
46
73
47
- // Replace the default IServiceProviderAccessor with on that can use IHttpContextAccessor to
48
- // resolve instances that are scoped inside the current request.
49
- options . ServiceProviderAccessor = new AspNetCoreServiceProviderAccessor (
50
- new HttpContextAccessor ( ) ,
51
- options . ServiceProviderAccessor ) ;
74
+ options . ServiceProviderAccessor = CreateServiceProviderAccessor ( options , serviceScopeBehavior ) ;
52
75
53
76
services . UseSimpleInjectorAspNetRequestScoping ( container ) ;
54
77
55
78
return new SimpleInjectorAspNetCoreBuilder ( options ) ;
56
79
}
80
+
81
+ private static IServiceProviderAccessor CreateServiceProviderAccessor (
82
+ SimpleInjectorAddOptions options , ServiceScopeReuseBehavior serviceScopeBehavior )
83
+ {
84
+ if ( serviceScopeBehavior < ServiceScopeReuseBehavior . OnePerRequest
85
+ || serviceScopeBehavior > ServiceScopeReuseBehavior . Unchanged )
86
+ {
87
+ throw new ArgumentOutOfRangeException ( nameof ( serviceScopeBehavior ) ) ;
88
+ }
89
+
90
+ if ( serviceScopeBehavior == ServiceScopeReuseBehavior . OnePerRequest )
91
+ {
92
+ // This IServiceProviderAccessor uses IHttpContextAccessor to resolve instances that are scoped inside
93
+ // the current request.
94
+ return new OnePerRequestServiceProviderAccessor (
95
+ new HttpContextAccessor ( ) ,
96
+ options . ServiceProviderAccessor ) ;
97
+ }
98
+ else if ( serviceScopeBehavior == ServiceScopeReuseBehavior . OnePerNestedScope )
99
+ {
100
+ // This IServiceProviderAccessor resolves cross-wired services from the request's IServiceScope, but
101
+ // uses a new IServiceScope within a nested scope.
102
+ return new OnePerNestedScopeServiceProviderAccessor ( options . Container , options . ServiceProviderAccessor ) ;
103
+ }
104
+ else
105
+ {
106
+ // This uses the default behavior.
107
+ return options . ServiceProviderAccessor ;
108
+ }
109
+ }
57
110
}
58
111
}
0 commit comments