@@ -76,7 +76,11 @@ private static void Finialize( EndpointBuilder endpointBuilder, ApiVersionSet? v
7676
7777 endpointBuilder . RequestDelegate = context =>
7878 {
79- context . RequestServices = new InjectApiVersion ( context ) ;
79+ if ( context . RequestServices is not InjectApiVersion )
80+ {
81+ context . RequestServices = new InjectApiVersion ( context ) ;
82+ }
83+
8084 return requestDelegate ( context ) ;
8185 } ;
8286 }
@@ -282,11 +286,12 @@ private record struct ApiVersionBuckets(
282286 && AdvertisedDeprecated . Count == 0 ;
283287 }
284288
285- private sealed class InjectApiVersion : IServiceProvider , IKeyedServiceProvider
289+ private sealed class InjectApiVersion : IKeyedServiceProvider , IServiceScopeFactory
286290 {
287- private static readonly Type ApiVersionType = typeof ( ApiVersion ) ;
288291 private readonly IServiceProvider provider ;
289292 private readonly HttpContext context ;
293+ internal static readonly Type ApiVersionType = typeof ( ApiVersion ) ;
294+ internal static readonly Type ServiceScopeFactoryType = typeof ( IServiceScopeFactory ) ;
290295
291296 public InjectApiVersion ( HttpContext context )
292297 {
@@ -295,6 +300,10 @@ public InjectApiVersion( HttpContext context )
295300 context . RequestServices = this ;
296301 }
297302
303+ #pragma warning disable CA2000 // Dispose objects before losing scope
304+ public IServiceScope CreateScope ( ) => new ApiVersionScope ( context , provider . CreateScope ( ) ) ;
305+ #pragma warning restore CA2000
306+
298307 public object ? GetKeyedService ( Type serviceType , object ? serviceKey ) =>
299308 provider . GetKeyedService ( serviceType , serviceKey ) ;
300309
@@ -307,8 +316,55 @@ public object GetRequiredKeyedService( Type serviceType, object? serviceKey ) =>
307316 {
308317 return context . RequestedApiVersion ;
309318 }
319+ else if ( serviceType . Equals ( ServiceScopeFactoryType ) )
320+ {
321+ return this ;
322+ }
310323
311324 return provider . GetService ( serviceType ) ;
312325 }
313326 }
327+
328+ private sealed class ApiVersionScope ( HttpContext context , IServiceScope scope )
329+ : IKeyedServiceProvider , IServiceScopeFactory , IServiceScope
330+ {
331+ private bool disposed ;
332+
333+ public IServiceProvider ServiceProvider => this ;
334+
335+ #pragma warning disable CA2000 // Dispose objects before losing scope
336+ public IServiceScope CreateScope ( ) => new ApiVersionScope ( context , scope . ServiceProvider . CreateScope ( ) ) ;
337+ #pragma warning restore CA2000
338+
339+ public object ? GetKeyedService ( Type serviceType , object ? serviceKey ) =>
340+ scope . ServiceProvider . GetKeyedService ( serviceType , serviceKey ) ;
341+
342+ public object GetRequiredKeyedService ( Type serviceType , object ? serviceKey ) =>
343+ scope . ServiceProvider . GetRequiredKeyedService ( serviceType , serviceKey ) ;
344+
345+ public object ? GetService ( Type serviceType )
346+ {
347+ if ( serviceType . IsAssignableFrom ( InjectApiVersion . ApiVersionType ) )
348+ {
349+ return context . RequestedApiVersion ;
350+ }
351+ else if ( serviceType . Equals ( InjectApiVersion . ServiceScopeFactoryType ) )
352+ {
353+ return this ;
354+ }
355+
356+ return scope . ServiceProvider . GetService ( serviceType ) ;
357+ }
358+
359+ public void Dispose ( )
360+ {
361+ if ( disposed )
362+ {
363+ return ;
364+ }
365+
366+ disposed = true ;
367+ scope . Dispose ( ) ;
368+ }
369+ }
314370}
0 commit comments