1+ using System ;
2+ using FluentAssertions ;
3+ using Microsoft . Extensions . DependencyInjection ;
4+ using Microsoft . Extensions . DependencyInjection . Extensions ;
5+ using Ninject . Web . AspNetCore . Test . Fakes ;
6+ using Xunit ;
7+
8+ namespace Ninject . Web . AspNetCore . Test . Unit ;
9+
10+ public class ServiceProviderScopeTest : TestKernelContext
11+ {
12+ [ Theory ]
13+ [ MemberData ( nameof ( ServiceConfigurations ) ) ]
14+ public void ScopedServices_ResolvedInScope_ShouldBeDifferent ( ServiceCollection serviceCollection )
15+ {
16+ var kernel = CreateKernel ( serviceCollection ) ;
17+ var provider = kernel . Get < IServiceProvider > ( ) ;
18+
19+ var rootKnight = provider . GetRequiredService < Knight > ( ) ;
20+
21+ using ( var scope = provider . CreateScope ( ) )
22+ {
23+ // The IWeapon instantiated inside of this scope should also be tied to this scope when created through
24+ // a ServiceDescriptor.ImplementationFactory
25+ var levelOneKnight = scope . ServiceProvider . GetRequiredService < Knight > ( ) ;
26+ AssertNotSameKnightAndWeapon ( levelOneKnight , rootKnight ) ;
27+
28+ var levelOneKnight2 = scope . ServiceProvider . GetRequiredService < Knight > ( ) ;
29+ AssertSameKnightAndWeapon ( levelOneKnight2 , levelOneKnight ) ;
30+ }
31+
32+ var rootKnight2 = provider . GetRequiredService < Knight > ( ) ;
33+ AssertSameKnightAndWeapon ( rootKnight2 , rootKnight ) ;
34+ }
35+
36+ private void AssertSameKnightAndWeapon ( Knight value , Knight expected )
37+ {
38+ value . Should ( ) . BeSameAs ( expected ) ;
39+ value . Weapon . Should ( ) . BeSameAs ( expected . Weapon ) ;
40+ }
41+
42+ private void AssertNotSameKnightAndWeapon ( Knight value , Knight expected )
43+ {
44+ value . Should ( ) . NotBeSameAs ( expected ) ;
45+ value . Weapon . Should ( ) . NotBeSameAs ( expected . Weapon ) ;
46+ }
47+
48+ public static TheoryData < ServiceCollection > ServiceConfigurations => new TheoryData < ServiceCollection >
49+ {
50+ {
51+ new ServiceCollection ( ) {
52+ new ServiceDescriptor ( typeof ( Knight ) , typeof ( Knight ) , ServiceLifetime . Scoped ) ,
53+ new ServiceDescriptor ( typeof ( IWeapon ) , typeof ( Longsword ) , ServiceLifetime . Scoped )
54+ }
55+ } ,
56+ {
57+ new ServiceCollection ( ) {
58+ new ServiceDescriptor ( typeof ( Knight ) , typeof ( Knight ) , ServiceLifetime . Scoped ) ,
59+ new ServiceDescriptor ( typeof ( Longsword ) , typeof ( Longsword ) , ServiceLifetime . Scoped ) ,
60+ // See https://github.com/lord-executor/Ninject.Web.AspNetCore/issues/12
61+ // The difference here is the use of a descriptor with an implementation factory where the implementation
62+ // must make sure that the correct _scoped_ IServiceProvider instance is passed to the factory
63+ new ServiceDescriptor ( typeof ( IWeapon ) , serviceProvider => serviceProvider . GetService < Longsword > ( ) , ServiceLifetime . Scoped )
64+ }
65+ } ,
66+ } ;
67+ }
0 commit comments