@@ -34,15 +34,13 @@ namespace JsonApiDotNetCore.Builders
34
34
internal sealed class JsonApiApplicationBuilder
35
35
{
36
36
private readonly JsonApiOptions _options = new JsonApiOptions ( ) ;
37
- private IResourceGraphBuilder _resourceGraphBuilder ;
38
- private Type _dbContextType ;
39
- private Action < IResourceGraphBuilder > _configureResources ;
40
- private Action < IServiceDiscoveryFacade > _configureAutoDiscovery ;
41
37
private readonly IServiceCollection _services ;
42
38
private IServiceDiscoveryFacade _serviceDiscoveryFacade ;
39
+ private IResourceGraphBuilder _resourceGraphBuilder ;
43
40
private readonly IMvcCoreBuilder _mvcBuilder ;
44
41
45
- public JsonApiApplicationBuilder ( IServiceCollection services , IMvcCoreBuilder mvcBuilder )
42
+ public JsonApiApplicationBuilder ( IServiceCollection services ,
43
+ IMvcCoreBuilder mvcBuilder )
46
44
{
47
45
_services = services ;
48
46
_mvcBuilder = mvcBuilder ;
@@ -51,19 +49,11 @@ public JsonApiApplicationBuilder(IServiceCollection services, IMvcCoreBuilder mv
51
49
/// <summary>
52
50
/// Executes the action provided by the user to configure <see cref="JsonApiOptions"/>
53
51
/// </summary>
54
- public void ConfigureJsonApiOptions ( Action < JsonApiOptions > options )
55
- {
56
- options ? . Invoke ( _options ) ;
57
- }
58
-
59
- public void RegisterResourceSources ( Type dbContextType , Action < IServiceDiscoveryFacade > autoDiscovery ,
60
- Action < IResourceGraphBuilder > resources )
52
+ public void ConfigureJsonApiOptions ( Action < JsonApiOptions > configureOptions )
61
53
{
62
- _dbContextType = dbContextType ;
63
- _configureAutoDiscovery = autoDiscovery ;
64
- _configureResources = resources ;
54
+ configureOptions ? . Invoke ( _options ) ;
65
55
}
66
-
56
+
67
57
/// <summary>
68
58
/// Configures built-in .NET Core MVC (things like middleware, routing). Most of this configuration can be adjusted for the developers' need.
69
59
/// Before calling .AddJsonApi(), a developer can register their own implementation of the following services to customize startup:
@@ -72,24 +62,16 @@ public void RegisterResourceSources(Type dbContextType, Action<IServiceDiscovery
72
62
/// </summary>
73
63
public void ConfigureMvc ( )
74
64
{
75
- RegisterJsonApiStartupServices ( ) ;
76
-
77
- using ( var resourceConfigurationIntermediateProvider = _services . BuildServiceProvider ( ) )
78
- {
79
- _resourceGraphBuilder = resourceConfigurationIntermediateProvider . GetRequiredService < IResourceGraphBuilder > ( ) ;
80
- _serviceDiscoveryFacade = resourceConfigurationIntermediateProvider . GetRequiredService < IServiceDiscoveryFacade > ( ) ;
81
- _services . AddSingleton ( BuildResourceGraph ( resourceConfigurationIntermediateProvider ) ) ;
82
- }
83
-
84
65
IJsonApiExceptionFilterProvider exceptionFilterProvider ;
85
66
IJsonApiTypeMatchFilterProvider typeMatchFilterProvider ;
86
67
IJsonApiRoutingConvention routingConvention ;
87
68
88
- using ( var middlewareConfigurationIntermediateProvider = _services . BuildServiceProvider ( ) )
69
+ using ( var intermediateProvider = _services . BuildServiceProvider ( ) )
89
70
{
90
- exceptionFilterProvider = middlewareConfigurationIntermediateProvider . GetRequiredService < IJsonApiExceptionFilterProvider > ( ) ;
91
- typeMatchFilterProvider = middlewareConfigurationIntermediateProvider . GetRequiredService < IJsonApiTypeMatchFilterProvider > ( ) ;
92
- routingConvention = middlewareConfigurationIntermediateProvider . GetRequiredService < IJsonApiRoutingConvention > ( ) ;
71
+ exceptionFilterProvider = intermediateProvider . GetRequiredService < IJsonApiExceptionFilterProvider > ( ) ;
72
+ typeMatchFilterProvider = intermediateProvider . GetRequiredService < IJsonApiTypeMatchFilterProvider > ( ) ;
73
+ routingConvention = intermediateProvider . GetRequiredService < IJsonApiRoutingConvention > ( ) ;
74
+ _services . AddSingleton < IControllerResourceMapping > ( routingConvention ) ;
93
75
}
94
76
95
77
_mvcBuilder . AddMvcOptions ( options =>
@@ -107,20 +89,41 @@ public void ConfigureMvc()
107
89
{
108
90
_mvcBuilder . AddDataAnnotations ( ) ;
109
91
}
110
-
111
- _services . AddSingleton < IControllerResourceMapping > ( routingConvention ) ;
112
92
}
113
93
94
+ /// <summary>
95
+ /// Configures and build the resource graph with resources from the provided sources and adds it to the DI container.
96
+ /// </summary>
97
+ public void AddResourceGraph ( Type dbContextType , Action < IResourceGraphBuilder > configureResources )
98
+ {
99
+ using var intermediateProvider = _services . BuildServiceProvider ( ) ;
100
+ AddResourcesFromDbContext ( dbContextType , intermediateProvider , _resourceGraphBuilder ) ;
101
+ AutoDiscoverResources ( _serviceDiscoveryFacade ) ;
102
+ UserConfigureResources ( configureResources , _resourceGraphBuilder ) ;
103
+ _services . AddSingleton ( _resourceGraphBuilder . Build ( ) ) ;
104
+ }
105
+
106
+ public void ConfigureAutoDiscovery ( Action < IServiceDiscoveryFacade > configureAutoDiscovery )
107
+ {
108
+ using var intermediateProvider = _services . BuildServiceProvider ( ) ;
109
+ _serviceDiscoveryFacade = intermediateProvider . GetRequiredService < IServiceDiscoveryFacade > ( ) ;
110
+ _resourceGraphBuilder = intermediateProvider . GetRequiredService < IResourceGraphBuilder > ( ) ;
111
+ RegisterDiscoverableAssemblies ( configureAutoDiscovery , _serviceDiscoveryFacade ) ;
112
+ }
113
+
114
+ private void RegisterDiscoverableAssemblies ( Action < IServiceDiscoveryFacade > configureAutoDiscovery , IServiceDiscoveryFacade serviceDiscoveryFacade )
115
+ {
116
+ configureAutoDiscovery ? . Invoke ( serviceDiscoveryFacade ) ;
117
+ }
118
+
114
119
/// <summary>
115
120
/// Registers the remaining internals.
116
121
/// </summary>
117
- public void ConfigureServices ( )
122
+ public void ConfigureServices ( Type dbContextType )
118
123
{
119
- _serviceDiscoveryFacade . DiscoverServices ( ) ;
120
-
121
- if ( _dbContextType != null )
124
+ if ( dbContextType != null )
122
125
{
123
- var contextResolverType = typeof ( DbContextResolver < > ) . MakeGenericType ( _dbContextType ) ;
126
+ var contextResolverType = typeof ( DbContextResolver < > ) . MakeGenericType ( dbContextType ) ;
124
127
_services . AddScoped ( typeof ( IDbContextResolver ) , contextResolverType ) ;
125
128
}
126
129
else
@@ -129,12 +132,56 @@ public void ConfigureServices()
129
132
_services . AddSingleton ( new DbContextOptionsBuilder ( ) . Options ) ;
130
133
}
131
134
135
+ AddRepositoryLayer ( ) ;
136
+ AddServiceLayer ( ) ;
137
+
138
+ _services . AddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
139
+ _services . AddSingleton < IResourceContextProvider > ( sp => sp . GetRequiredService < IResourceGraph > ( ) ) ;
140
+ _services . AddSingleton < IExceptionHandler , ExceptionHandler > ( ) ;
141
+
142
+ _services . AddScoped < ICurrentRequest , CurrentRequest > ( ) ;
143
+ _services . AddScoped < IScopedServiceProvider , RequestScopedServiceProvider > ( ) ;
144
+ _services . AddScoped < IJsonApiWriter , JsonApiWriter > ( ) ;
145
+ _services . AddScoped < IJsonApiReader , JsonApiReader > ( ) ;
146
+ _services . AddScoped < IGenericServiceFactory , GenericServiceFactory > ( ) ;
147
+ _services . AddScoped ( typeof ( RepositoryRelationshipUpdateHelper < > ) ) ;
148
+ _services . AddScoped < ITargetedFields , TargetedFields > ( ) ;
149
+ _services . AddScoped < IResourceDefinitionProvider , ResourceDefinitionProvider > ( ) ;
150
+ _services . AddScoped < IFieldsToSerialize , FieldsToSerialize > ( ) ;
151
+ _services . AddScoped ( typeof ( IResourceChangeTracker < > ) , typeof ( ResourceChangeTracker < > ) ) ;
152
+ _services . AddScoped < IResourceFactory , ResourceFactory > ( ) ;
153
+ _services . AddScoped < IPaginationContext , PaginationContext > ( ) ;
154
+ _services . AddScoped < IQueryLayerComposer , QueryLayerComposer > ( ) ;
155
+
156
+ AddServerSerialization ( ) ;
157
+ AddQueryStringParameterServices ( ) ;
158
+ if ( _options . EnableResourceHooks )
159
+ {
160
+ AddResourceHooks ( ) ;
161
+ }
162
+
163
+ _services . AddScoped < IInverseRelationships , InverseRelationships > ( ) ;
164
+ }
165
+
166
+ /// <summary>
167
+ /// Discovers DI registrable services in the assemblies marked for discovery.
168
+ /// </summary>
169
+ public void DiscoverServices ( )
170
+ {
171
+ _serviceDiscoveryFacade . DiscoverServices ( ) ;
172
+ }
173
+
174
+ private void AddRepositoryLayer ( )
175
+ {
132
176
_services . AddScoped ( typeof ( IResourceRepository < > ) , typeof ( EntityFrameworkCoreRepository < > ) ) ;
133
177
_services . AddScoped ( typeof ( IResourceRepository < , > ) , typeof ( EntityFrameworkCoreRepository < , > ) ) ;
134
178
135
179
_services . AddScoped ( typeof ( IResourceReadRepository < , > ) , typeof ( EntityFrameworkCoreRepository < , > ) ) ;
136
180
_services . AddScoped ( typeof ( IResourceWriteRepository < , > ) , typeof ( EntityFrameworkCoreRepository < , > ) ) ;
181
+ }
137
182
183
+ private void AddServiceLayer ( )
184
+ {
138
185
_services . AddScoped ( typeof ( ICreateService < > ) , typeof ( JsonApiResourceService < > ) ) ;
139
186
_services . AddScoped ( typeof ( ICreateService < , > ) , typeof ( JsonApiResourceService < , > ) ) ;
140
187
@@ -161,33 +208,6 @@ public void ConfigureServices()
161
208
162
209
_services . AddScoped ( typeof ( IResourceQueryService < , > ) , typeof ( JsonApiResourceService < , > ) ) ;
163
210
_services . AddScoped ( typeof ( IResourceCommandService < , > ) , typeof ( JsonApiResourceService < , > ) ) ;
164
-
165
- _services . AddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
166
- _services . AddSingleton < IResourceContextProvider > ( sp => sp . GetRequiredService < IResourceGraph > ( ) ) ;
167
- _services . AddSingleton < IExceptionHandler , ExceptionHandler > ( ) ;
168
-
169
- _services . AddScoped < ICurrentRequest , CurrentRequest > ( ) ;
170
- _services . AddScoped < IScopedServiceProvider , RequestScopedServiceProvider > ( ) ;
171
- _services . AddScoped < IJsonApiWriter , JsonApiWriter > ( ) ;
172
- _services . AddScoped < IJsonApiReader , JsonApiReader > ( ) ;
173
- _services . AddScoped < IGenericServiceFactory , GenericServiceFactory > ( ) ;
174
- _services . AddScoped ( typeof ( RepositoryRelationshipUpdateHelper < > ) ) ;
175
- _services . AddScoped < ITargetedFields , TargetedFields > ( ) ;
176
- _services . AddScoped < IResourceDefinitionProvider , ResourceDefinitionProvider > ( ) ;
177
- _services . AddScoped < IFieldsToSerialize , FieldsToSerialize > ( ) ;
178
- _services . AddScoped ( typeof ( IResourceChangeTracker < > ) , typeof ( ResourceChangeTracker < > ) ) ;
179
- _services . AddScoped < IResourceFactory , ResourceFactory > ( ) ;
180
- _services . AddScoped < IPaginationContext , PaginationContext > ( ) ;
181
- _services . AddScoped < IQueryLayerComposer , QueryLayerComposer > ( ) ;
182
-
183
- AddServerSerialization ( ) ;
184
- AddQueryStringParameterServices ( ) ;
185
- if ( _options . EnableResourceHooks )
186
- {
187
- AddResourceHooks ( ) ;
188
- }
189
-
190
- _services . AddScoped < IInverseRelationships , InverseRelationships > ( ) ;
191
211
}
192
212
193
213
private void AddQueryStringParameterServices ( )
@@ -244,7 +264,10 @@ private void AddServerSerialization()
244
264
_services . AddScoped < IResourceObjectBuilder , ResponseResourceObjectBuilder > ( ) ;
245
265
}
246
266
247
- private void RegisterJsonApiStartupServices ( )
267
+ /// <summary>
268
+ /// Registers services that are required for the configuration of JsonApiDotNetCore during the start up.
269
+ /// </summary>
270
+ public void RegisterJsonApiStartupServices ( )
248
271
{
249
272
_services . AddSingleton < IJsonApiOptions > ( _options ) ;
250
273
_services . TryAddSingleton < IJsonApiRoutingConvention , JsonApiRoutingConvention > ( ) ;
@@ -254,43 +277,33 @@ private void RegisterJsonApiStartupServices()
254
277
_services . TryAddScoped < IJsonApiTypeMatchFilterProvider , JsonApiTypeMatchFilterProvider > ( ) ;
255
278
}
256
279
257
- private IResourceGraph BuildResourceGraph ( ServiceProvider intermediateProvider )
258
- {
259
- AddResourceTypesFromDbContext ( intermediateProvider ) ;
260
- AutoDiscoverResources ( ) ;
261
- ConfigureResources ( ) ;
262
-
263
- return _resourceGraphBuilder . Build ( ) ;
264
- }
265
-
266
- private void AddResourceTypesFromDbContext ( ServiceProvider intermediateProvider )
280
+ private void AddResourcesFromDbContext ( Type dbContextType , ServiceProvider intermediateProvider , IResourceGraphBuilder builder )
267
281
{
268
- if ( _dbContextType != null )
282
+ if ( dbContextType != null )
269
283
{
270
- var dbContext = ( DbContext ) intermediateProvider . GetRequiredService ( _dbContextType ) ;
284
+ var dbContext = ( DbContext ) intermediateProvider . GetRequiredService ( dbContextType ) ;
271
285
272
286
foreach ( var entityType in dbContext . Model . GetEntityTypes ( ) )
273
287
{
274
- _resourceGraphBuilder . AddResource ( entityType . ClrType ) ;
288
+ builder . AddResource ( entityType . ClrType ) ;
275
289
}
276
290
}
277
291
}
278
292
279
293
/// <summary>
280
294
/// Performs auto-discovery of JsonApiDotNetCore services.
281
295
/// </summary>
282
- private void AutoDiscoverResources ( )
296
+ private void AutoDiscoverResources ( IServiceDiscoveryFacade serviceDiscoveryFacade )
283
297
{
284
- _configureAutoDiscovery ? . Invoke ( _serviceDiscoveryFacade ) ;
285
- _serviceDiscoveryFacade . DiscoverResources ( ) ;
298
+ serviceDiscoveryFacade . DiscoverResources ( ) ;
286
299
}
287
300
288
301
/// <summary>
289
302
/// Executes the action provided by the user to configure the resources using <see cref="IResourceGraphBuilder"/>
290
303
/// </summary>
291
- private void ConfigureResources ( )
304
+ private void UserConfigureResources ( Action < IResourceGraphBuilder > configureResources , IResourceGraphBuilder resourceGraphBuilder )
292
305
{
293
- _configureResources ? . Invoke ( _resourceGraphBuilder ) ;
306
+ configureResources ? . Invoke ( resourceGraphBuilder ) ;
294
307
}
295
308
}
296
309
}
0 commit comments