6
6
using Microsoft . EntityFrameworkCore ;
7
7
using Microsoft . Extensions . DependencyInjection ;
8
8
using System ;
9
+ using System . Collections . Generic ;
9
10
using System . Linq ;
10
11
using System . Reflection ;
11
12
12
13
namespace JsonApiDotNetCore . Graph
13
14
{
14
15
public class ServiceDiscoveryFacade
15
16
{
17
+ internal static HashSet < Type > ServiceInterfaces = new HashSet < Type > {
18
+ typeof ( IResourceService < > ) ,
19
+ typeof ( IResourceService < , > ) ,
20
+ typeof ( ICreateService < > ) ,
21
+ typeof ( ICreateService < , > ) ,
22
+ typeof ( IGetAllService < > ) ,
23
+ typeof ( IGetAllService < , > ) ,
24
+ typeof ( IGetByIdService < > ) ,
25
+ typeof ( IGetByIdService < , > ) ,
26
+ typeof ( IGetRelationshipService < > ) ,
27
+ typeof ( IGetRelationshipService < , > ) ,
28
+ typeof ( IUpdateService < > ) ,
29
+ typeof ( IUpdateService < , > ) ,
30
+ typeof ( IDeleteService < > ) ,
31
+ typeof ( IDeleteService < , > )
32
+ } ;
33
+
34
+ internal static HashSet < Type > RepositoryInterfaces = new HashSet < Type > {
35
+ typeof ( IEntityRepository < > ) ,
36
+ typeof ( IEntityRepository < , > ) ,
37
+ typeof ( IEntityWriteRepository < > ) ,
38
+ typeof ( IEntityWriteRepository < , > ) ,
39
+ typeof ( IEntityReadRepository < > ) ,
40
+ typeof ( IEntityReadRepository < , > )
41
+ } ;
42
+
16
43
private readonly IServiceCollection _services ;
17
44
private readonly IContextGraphBuilder _graphBuilder ;
45
+ private readonly List < ResourceDescriptor > _identifiables = new List < ResourceDescriptor > ( ) ;
18
46
19
- public ServiceDiscoveryFacade ( IServiceCollection services , IContextGraphBuilder graphBuilder )
47
+ public ServiceDiscoveryFacade (
48
+ IServiceCollection services ,
49
+ IContextGraphBuilder graphBuilder )
20
50
{
21
51
_services = services ;
22
52
_graphBuilder = graphBuilder ;
@@ -26,20 +56,25 @@ public ServiceDiscoveryFacade(IServiceCollection services, IContextGraphBuilder
26
56
/// Add resources, services and repository implementations to the container.
27
57
/// </summary>
28
58
/// <param name="resourceNameFormatter">The type name formatter used to get the string representation of resource names.</param>
29
- public ServiceDiscoveryFacade AddCurrentAssemblyServices ( IResourceNameFormatter resourceNameFormatter = null )
30
- => AddAssemblyServices ( Assembly . GetCallingAssembly ( ) , resourceNameFormatter ) ;
59
+ public ServiceDiscoveryFacade AddCurrentAssembly ( IResourceNameFormatter resourceNameFormatter = null )
60
+ => AddAssembly ( Assembly . GetCallingAssembly ( ) , resourceNameFormatter ) ;
31
61
32
62
/// <summary>
33
63
/// Add resources, services and repository implementations to the container.
34
64
/// </summary>
35
65
/// <param name="assembly">The assembly to search for resources in.</param>
36
66
/// <param name="resourceNameFormatter">The type name formatter used to get the string representation of resource names.</param>
37
- public ServiceDiscoveryFacade AddAssemblyServices ( Assembly assembly , IResourceNameFormatter resourceNameFormatter = null )
67
+ public ServiceDiscoveryFacade AddAssembly ( Assembly assembly , IResourceNameFormatter resourceNameFormatter = null )
38
68
{
39
69
AddDbContextResolvers ( assembly ) ;
40
- AddAssemblyResources ( assembly , resourceNameFormatter ) ;
41
- AddAssemblyServices ( assembly ) ;
42
- AddAssemblyRepositories ( assembly ) ;
70
+
71
+ var resourceDescriptors = TypeLocator . GetIdentifableTypes ( assembly ) ;
72
+ foreach ( var resourceDescriptor in resourceDescriptors )
73
+ {
74
+ AddResource ( assembly , resourceDescriptor , resourceNameFormatter ) ;
75
+ AddServices ( assembly , resourceDescriptor ) ;
76
+ AddRepositories ( assembly , resourceDescriptor ) ;
77
+ }
43
78
44
79
return this ;
45
80
}
@@ -59,18 +94,21 @@ private void AddDbContextResolvers(Assembly assembly)
59
94
/// </summary>
60
95
/// <param name="assembly">The assembly to search for resources in.</param>
61
96
/// <param name="resourceNameFormatter">The type name formatter used to get the string representation of resource names.</param>
62
- public ServiceDiscoveryFacade AddAssemblyResources ( Assembly assembly , IResourceNameFormatter resourceNameFormatter = null )
97
+ public ServiceDiscoveryFacade AddResources ( Assembly assembly , IResourceNameFormatter resourceNameFormatter = null )
63
98
{
64
99
var identifiables = TypeLocator . GetIdentifableTypes ( assembly ) ;
65
100
foreach ( var identifiable in identifiables )
66
- {
67
- RegisterResourceDefinition ( assembly , identifiable ) ;
68
- AddResourceToGraph ( identifiable , resourceNameFormatter ) ;
69
- }
101
+ AddResource ( assembly , identifiable , resourceNameFormatter ) ;
70
102
71
103
return this ;
72
104
}
73
105
106
+ private void AddResource ( Assembly assembly , ResourceDescriptor resourceDescriptor , IResourceNameFormatter resourceNameFormatter = null )
107
+ {
108
+ RegisterResourceDefinition ( assembly , resourceDescriptor ) ;
109
+ AddResourceToGraph ( resourceDescriptor , resourceNameFormatter ) ;
110
+ }
111
+
74
112
private void RegisterResourceDefinition ( Assembly assembly , ResourceDescriptor identifiable )
75
113
{
76
114
try
@@ -83,9 +121,7 @@ private void RegisterResourceDefinition(Assembly assembly, ResourceDescriptor id
83
121
}
84
122
catch ( InvalidOperationException e )
85
123
{
86
- // TODO: need a better way to communicate failure since this is unlikely to occur during a web request
87
- throw new JsonApiException ( 500 ,
88
- $ "Cannot define multiple ResourceDefinition<> implementations for '{ identifiable . ResourceType } '", e ) ;
124
+ throw new JsonApiSetupException ( $ "Cannot define multiple ResourceDefinition<> implementations for '{ identifiable . ResourceType } '", e ) ;
89
125
}
90
126
}
91
127
@@ -105,61 +141,45 @@ private string FormatResourceName(Type resourceType, IResourceNameFormatter reso
105
141
/// Add <see cref="IResourceService{T, TId}"/> implementations to container.
106
142
/// </summary>
107
143
/// <param name="assembly">The assembly to search for resources in.</param>
108
- public ServiceDiscoveryFacade AddAssemblyServices ( Assembly assembly )
144
+ public ServiceDiscoveryFacade AddServices ( Assembly assembly )
109
145
{
110
- RegisterServiceImplementations ( assembly , typeof ( IResourceService < > ) ) ;
111
- RegisterServiceImplementations ( assembly , typeof ( IResourceService < , > ) ) ;
112
-
113
- RegisterServiceImplementations ( assembly , typeof ( ICreateService < > ) ) ;
114
- RegisterServiceImplementations ( assembly , typeof ( ICreateService < , > ) ) ;
115
-
116
- RegisterServiceImplementations ( assembly , typeof ( IGetAllService < > ) ) ;
117
- RegisterServiceImplementations ( assembly , typeof ( IGetAllService < , > ) ) ;
118
-
119
- RegisterServiceImplementations ( assembly , typeof ( IGetByIdService < > ) ) ;
120
- RegisterServiceImplementations ( assembly , typeof ( IGetByIdService < , > ) ) ;
121
-
122
- RegisterServiceImplementations ( assembly , typeof ( IGetRelationshipService < > ) ) ;
123
- RegisterServiceImplementations ( assembly , typeof ( IGetRelationshipService < , > ) ) ;
124
-
125
- RegisterServiceImplementations ( assembly , typeof ( IUpdateService < > ) ) ;
126
- RegisterServiceImplementations ( assembly , typeof ( IUpdateService < , > ) ) ;
127
-
128
- RegisterServiceImplementations ( assembly , typeof ( IDeleteService < > ) ) ;
129
- RegisterServiceImplementations ( assembly , typeof ( IDeleteService < , > ) ) ;
146
+ var resourceDescriptors = TypeLocator . GetIdentifableTypes ( assembly ) ;
147
+ foreach ( var resourceDescriptor in resourceDescriptors )
148
+ AddServices ( assembly , resourceDescriptor ) ;
130
149
131
150
return this ;
132
151
}
133
152
153
+ private void AddServices ( Assembly assembly , ResourceDescriptor resourceDescriptor )
154
+ {
155
+ foreach ( var serviceInterface in ServiceInterfaces )
156
+ RegisterServiceImplementations ( assembly , serviceInterface , resourceDescriptor ) ;
157
+ }
158
+
134
159
/// <summary>
135
160
/// Add <see cref="IEntityRepository{T, TId}"/> implementations to container.
136
161
/// </summary>
137
162
/// <param name="assembly">The assembly to search for resources in.</param>
138
- public ServiceDiscoveryFacade AddAssemblyRepositories ( Assembly assembly )
163
+ public ServiceDiscoveryFacade AddRepositories ( Assembly assembly )
139
164
{
140
- RegisterServiceImplementations ( assembly , typeof ( IEntityRepository < > ) ) ;
141
- RegisterServiceImplementations ( assembly , typeof ( IEntityRepository < , > ) ) ;
142
-
143
- RegisterServiceImplementations ( assembly , typeof ( IEntityWriteRepository < > ) ) ;
144
- RegisterServiceImplementations ( assembly , typeof ( IEntityWriteRepository < , > ) ) ;
145
-
146
- RegisterServiceImplementations ( assembly , typeof ( IEntityReadRepository < > ) ) ;
147
- RegisterServiceImplementations ( assembly , typeof ( IEntityReadRepository < , > ) ) ;
165
+ var resourceDescriptors = TypeLocator . GetIdentifableTypes ( assembly ) ;
166
+ foreach ( var resourceDescriptor in resourceDescriptors )
167
+ AddRepositories ( assembly , resourceDescriptor ) ;
148
168
149
169
return this ;
150
170
}
151
171
152
- private ServiceDiscoveryFacade RegisterServiceImplementations ( Assembly assembly , Type interfaceType )
172
+ private void AddRepositories ( Assembly assembly , ResourceDescriptor resourceDescriptor )
153
173
{
154
- var identifiables = TypeLocator . GetIdentifableTypes ( assembly ) ;
155
- foreach ( var identifiable in identifiables )
156
- {
157
- var service = TypeLocator . GetGenericInterfaceImplementation ( assembly , interfaceType , identifiable . ResourceType , identifiable . IdType ) ;
158
- if ( service . implementation != null )
159
- _services . AddScoped ( service . registrationInterface , service . implementation ) ;
160
- }
174
+ foreach ( var serviceInterface in RepositoryInterfaces )
175
+ RegisterServiceImplementations ( assembly , serviceInterface , resourceDescriptor ) ;
176
+ }
161
177
162
- return this ;
178
+ private void RegisterServiceImplementations ( Assembly assembly , Type interfaceType , ResourceDescriptor resourceDescriptor )
179
+ {
180
+ var service = TypeLocator . GetGenericInterfaceImplementation ( assembly , interfaceType , resourceDescriptor . ResourceType , resourceDescriptor . IdType ) ;
181
+ if ( service . implementation != null )
182
+ _services . AddScoped ( service . registrationInterface , service . implementation ) ;
163
183
}
164
184
}
165
185
}
0 commit comments