66using Microsoft . EntityFrameworkCore ;
77using Microsoft . Extensions . DependencyInjection ;
88using System ;
9+ using System . Collections . Generic ;
910using System . Linq ;
1011using System . Reflection ;
1112
1213namespace JsonApiDotNetCore . Graph
1314{
1415 public class ServiceDiscoveryFacade
1516 {
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+
1643 private readonly IServiceCollection _services ;
1744 private readonly IContextGraphBuilder _graphBuilder ;
45+ private readonly List < ResourceDescriptor > _identifiables = new List < ResourceDescriptor > ( ) ;
1846
19- public ServiceDiscoveryFacade ( IServiceCollection services , IContextGraphBuilder graphBuilder )
47+ public ServiceDiscoveryFacade (
48+ IServiceCollection services ,
49+ IContextGraphBuilder graphBuilder )
2050 {
2151 _services = services ;
2252 _graphBuilder = graphBuilder ;
@@ -26,20 +56,25 @@ public ServiceDiscoveryFacade(IServiceCollection services, IContextGraphBuilder
2656 /// Add resources, services and repository implementations to the container.
2757 /// </summary>
2858 /// <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 ) ;
3161
3262 /// <summary>
3363 /// Add resources, services and repository implementations to the container.
3464 /// </summary>
3565 /// <param name="assembly">The assembly to search for resources in.</param>
3666 /// <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 )
3868 {
3969 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+ }
4378
4479 return this ;
4580 }
@@ -59,18 +94,21 @@ private void AddDbContextResolvers(Assembly assembly)
5994 /// </summary>
6095 /// <param name="assembly">The assembly to search for resources in.</param>
6196 /// <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 )
6398 {
6499 var identifiables = TypeLocator . GetIdentifableTypes ( assembly ) ;
65100 foreach ( var identifiable in identifiables )
66- {
67- RegisterResourceDefinition ( assembly , identifiable ) ;
68- AddResourceToGraph ( identifiable , resourceNameFormatter ) ;
69- }
101+ AddResource ( assembly , identifiable , resourceNameFormatter ) ;
70102
71103 return this ;
72104 }
73105
106+ private void AddResource ( Assembly assembly , ResourceDescriptor resourceDescriptor , IResourceNameFormatter resourceNameFormatter = null )
107+ {
108+ RegisterResourceDefinition ( assembly , resourceDescriptor ) ;
109+ AddResourceToGraph ( resourceDescriptor , resourceNameFormatter ) ;
110+ }
111+
74112 private void RegisterResourceDefinition ( Assembly assembly , ResourceDescriptor identifiable )
75113 {
76114 try
@@ -83,9 +121,7 @@ private void RegisterResourceDefinition(Assembly assembly, ResourceDescriptor id
83121 }
84122 catch ( InvalidOperationException e )
85123 {
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 ) ;
89125 }
90126 }
91127
@@ -105,61 +141,45 @@ private string FormatResourceName(Type resourceType, IResourceNameFormatter reso
105141 /// Add <see cref="IResourceService{T, TId}"/> implementations to container.
106142 /// </summary>
107143 /// <param name="assembly">The assembly to search for resources in.</param>
108- public ServiceDiscoveryFacade AddAssemblyServices ( Assembly assembly )
144+ public ServiceDiscoveryFacade AddServices ( Assembly assembly )
109145 {
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 ) ;
130149
131150 return this ;
132151 }
133152
153+ private void AddServices ( Assembly assembly , ResourceDescriptor resourceDescriptor )
154+ {
155+ foreach ( var serviceInterface in ServiceInterfaces )
156+ RegisterServiceImplementations ( assembly , serviceInterface , resourceDescriptor ) ;
157+ }
158+
134159 /// <summary>
135160 /// Add <see cref="IEntityRepository{T, TId}"/> implementations to container.
136161 /// </summary>
137162 /// <param name="assembly">The assembly to search for resources in.</param>
138- public ServiceDiscoveryFacade AddAssemblyRepositories ( Assembly assembly )
163+ public ServiceDiscoveryFacade AddRepositories ( Assembly assembly )
139164 {
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 ) ;
148168
149169 return this ;
150170 }
151171
152- private ServiceDiscoveryFacade RegisterServiceImplementations ( Assembly assembly , Type interfaceType )
172+ private void AddRepositories ( Assembly assembly , ResourceDescriptor resourceDescriptor )
153173 {
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+ }
161177
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 ) ;
163183 }
164184 }
165185}
0 commit comments