23
23
namespace JsonApiDotNetCore . Configuration ;
24
24
25
25
/// <summary>
26
- /// A utility class that builds a JsonApi application. It registers all required services and allows the user to override parts of the startup
26
+ /// A utility class that builds a JSON:API application. It registers all required services and allows the user to override parts of the startup
27
27
/// configuration.
28
28
/// </summary>
29
- internal sealed class JsonApiApplicationBuilder : IJsonApiApplicationBuilder , IDisposable
29
+ internal sealed class JsonApiApplicationBuilder : IJsonApiApplicationBuilder
30
30
{
31
- private readonly JsonApiOptions _options = new ( ) ;
32
31
private readonly IServiceCollection _services ;
33
32
private readonly IMvcCoreBuilder _mvcBuilder ;
34
- private readonly ResourceGraphBuilder _resourceGraphBuilder ;
35
- private readonly ServiceDiscoveryFacade _serviceDiscoveryFacade ;
36
- private readonly ServiceProvider _intermediateProvider ;
33
+ private readonly JsonApiOptions _options = new ( ) ;
34
+ private readonly ResourceDescriptorAssemblyCache _assemblyCache = new ( ) ;
37
35
38
36
public Action < MvcOptions > ? ConfigureMvcOptions { get ; set ; }
39
37
@@ -44,12 +42,6 @@ public JsonApiApplicationBuilder(IServiceCollection services, IMvcCoreBuilder mv
44
42
45
43
_services = services ;
46
44
_mvcBuilder = mvcBuilder ;
47
- _intermediateProvider = services . BuildServiceProvider ( ) ;
48
-
49
- var loggerFactory = _intermediateProvider . GetRequiredService < ILoggerFactory > ( ) ;
50
-
51
- _resourceGraphBuilder = new ResourceGraphBuilder ( _options , loggerFactory ) ;
52
- _serviceDiscoveryFacade = new ServiceDiscoveryFacade ( _services , _resourceGraphBuilder , loggerFactory ) ;
53
45
}
54
46
55
47
/// <summary>
@@ -61,35 +53,51 @@ public void ConfigureJsonApiOptions(Action<JsonApiOptions>? configureOptions)
61
53
}
62
54
63
55
/// <summary>
64
- /// Executes the action provided by the user to configure <see cref="ServiceDiscoveryFacade" /> .
56
+ /// Executes the action provided by the user to configure auto-discovery .
65
57
/// </summary>
66
58
public void ConfigureAutoDiscovery ( Action < ServiceDiscoveryFacade > ? configureAutoDiscovery )
67
59
{
68
- configureAutoDiscovery ? . Invoke ( _serviceDiscoveryFacade ) ;
60
+ if ( configureAutoDiscovery != null )
61
+ {
62
+ var facade = new ServiceDiscoveryFacade ( _assemblyCache ) ;
63
+ configureAutoDiscovery . Invoke ( facade ) ;
64
+ }
69
65
}
70
66
71
67
/// <summary>
72
- /// Configures and builds the resource graph with resources from the provided sources and adds it to the DI container.
68
+ /// Configures and builds the resource graph with resources from the provided sources and adds them to the IoC container.
73
69
/// </summary>
74
70
public void ConfigureResourceGraph ( ICollection < Type > dbContextTypes , Action < ResourceGraphBuilder > ? configureResourceGraph )
75
71
{
76
72
ArgumentGuard . NotNull ( dbContextTypes ) ;
77
73
78
- _serviceDiscoveryFacade . DiscoverResources ( ) ;
79
-
80
- foreach ( Type dbContextType in dbContextTypes )
74
+ _services . TryAddSingleton ( serviceProvider =>
81
75
{
82
- var dbContext = ( DbContext ) _intermediateProvider . GetRequiredService ( dbContextType ) ;
83
- _resourceGraphBuilder . Add ( dbContext ) ;
84
- }
76
+ var loggerFactory = serviceProvider . GetRequiredService < ILoggerFactory > ( ) ;
77
+ var resourceGraphBuilder = new ResourceGraphBuilder ( _options , loggerFactory ) ;
85
78
86
- configureResourceGraph ? . Invoke ( _resourceGraphBuilder ) ;
79
+ var scanner = new ResourcesAssemblyScanner ( _assemblyCache , resourceGraphBuilder ) ;
80
+ scanner . DiscoverResources ( ) ;
87
81
88
- IResourceGraph resourceGraph = _resourceGraphBuilder . Build ( ) ;
82
+ if ( dbContextTypes . Count > 0 )
83
+ {
84
+ using IServiceScope scope = serviceProvider . CreateScope ( ) ;
89
85
90
- _options . SerializerOptions . Converters . Add ( new ResourceObjectConverter ( resourceGraph ) ) ;
86
+ foreach ( Type dbContextType in dbContextTypes )
87
+ {
88
+ var dbContext = ( DbContext ) scope . ServiceProvider . GetRequiredService ( dbContextType ) ;
89
+ resourceGraphBuilder . Add ( dbContext ) ;
90
+ }
91
+ }
92
+
93
+ configureResourceGraph ? . Invoke ( resourceGraphBuilder ) ;
94
+
95
+ IResourceGraph resourceGraph = resourceGraphBuilder . Build ( ) ;
96
+
97
+ _options . SerializerOptions . Converters . Add ( new ResourceObjectConverter ( resourceGraph ) ) ;
91
98
92
- _services . TryAddSingleton ( resourceGraph ) ;
99
+ return resourceGraph ;
100
+ } ) ;
93
101
}
94
102
95
103
/// <summary>
@@ -114,15 +122,16 @@ public void ConfigureMvc()
114
122
}
115
123
116
124
/// <summary>
117
- /// Discovers DI registrable services in the assemblies marked for discovery.
125
+ /// Registers injectables in the IoC container found in assemblies marked for auto- discovery.
118
126
/// </summary>
119
127
public void DiscoverInjectables ( )
120
128
{
121
- _serviceDiscoveryFacade . DiscoverInjectables ( ) ;
129
+ var scanner = new InjectablesAssemblyScanner ( _assemblyCache , _services ) ;
130
+ scanner . DiscoverInjectables ( ) ;
122
131
}
123
132
124
133
/// <summary>
125
- /// Registers the remaining internals.
134
+ /// Registers the remaining internals in the IoC container .
126
135
/// </summary>
127
136
public void ConfigureServiceContainer ( ICollection < Type > dbContextTypes )
128
137
{
@@ -182,15 +191,15 @@ private void AddMiddlewareLayer()
182
191
183
192
private void AddResourceLayer ( )
184
193
{
185
- RegisterImplementationForInterfaces ( ServiceDiscoveryFacade . ResourceDefinitionUnboundInterfaces , typeof ( JsonApiResourceDefinition < , > ) ) ;
194
+ RegisterImplementationForInterfaces ( InjectablesAssemblyScanner . ResourceDefinitionUnboundInterfaces , typeof ( JsonApiResourceDefinition < , > ) ) ;
186
195
187
196
_services . TryAddScoped < IResourceDefinitionAccessor , ResourceDefinitionAccessor > ( ) ;
188
197
_services . TryAddScoped < IResourceFactory , ResourceFactory > ( ) ;
189
198
}
190
199
191
200
private void AddRepositoryLayer ( )
192
201
{
193
- RegisterImplementationForInterfaces ( ServiceDiscoveryFacade . RepositoryUnboundInterfaces , typeof ( EntityFrameworkCoreRepository < , > ) ) ;
202
+ RegisterImplementationForInterfaces ( InjectablesAssemblyScanner . RepositoryUnboundInterfaces , typeof ( EntityFrameworkCoreRepository < , > ) ) ;
194
203
195
204
_services . TryAddScoped < IResourceRepositoryAccessor , ResourceRepositoryAccessor > ( ) ;
196
205
@@ -204,7 +213,7 @@ private void AddRepositoryLayer()
204
213
205
214
private void AddServiceLayer ( )
206
215
{
207
- RegisterImplementationForInterfaces ( ServiceDiscoveryFacade . ServiceUnboundInterfaces , typeof ( JsonApiResourceService < , > ) ) ;
216
+ RegisterImplementationForInterfaces ( InjectablesAssemblyScanner . ServiceUnboundInterfaces , typeof ( JsonApiResourceService < , > ) ) ;
208
217
}
209
218
210
219
private void RegisterImplementationForInterfaces ( HashSet < Type > unboundInterfaces , Type unboundImplementationType )
@@ -291,9 +300,4 @@ private void AddOperationsLayer()
291
300
_services . TryAddScoped < IOperationProcessorAccessor , OperationProcessorAccessor > ( ) ;
292
301
_services . TryAddScoped < ILocalIdTracker , LocalIdTracker > ( ) ;
293
302
}
294
-
295
- public void Dispose ( )
296
- {
297
- _intermediateProvider . Dispose ( ) ;
298
- }
299
303
}
0 commit comments