11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4- using JsonApiDotNetCore . Graph ;
54using JsonApiDotNetCore . Internal ;
65using JsonApiDotNetCore . Models ;
6+ using Microsoft . Extensions . DependencyInjection ;
77
88namespace JsonApiDotNetCore . Hooks
99{
@@ -12,78 +12,74 @@ namespace JsonApiDotNetCore.Hooks
1212 /// </summary>
1313 public class HooksDiscovery < TResource > : IHooksDiscovery < TResource > where TResource : class , IIdentifiable
1414 {
15+ private readonly Type _boundResourceDefinitionType = typeof ( ResourceDefinition < TResource > ) ;
1516 private readonly ResourceHook [ ] _allHooks ;
1617 private readonly ResourceHook [ ] _databaseValuesAttributeAllowed =
1718 {
1819 ResourceHook . BeforeUpdate ,
1920 ResourceHook . BeforeUpdateRelationship ,
2021 ResourceHook . BeforeDelete
2122 } ;
23+
2224 /// <inheritdoc/>
2325 public ResourceHook [ ] ImplementedHooks { get ; private set ; }
2426 public ResourceHook [ ] DatabaseValuesEnabledHooks { get ; private set ; }
2527 public ResourceHook [ ] DatabaseValuesDisabledHooks { get ; private set ; }
2628
27-
28- public HooksDiscovery ( )
29+ public HooksDiscovery ( IServiceProvider provider )
2930 {
3031 _allHooks = Enum . GetValues ( typeof ( ResourceHook ) )
3132 . Cast < ResourceHook > ( )
3233 . Where ( h => h != ResourceHook . None )
3334 . ToArray ( ) ;
34- DiscoverImplementedHooksForModel ( ) ;
35+
36+ Type containerType ;
37+ using ( var scope = provider . CreateScope ( ) )
38+ {
39+ containerType = scope . ServiceProvider . GetService ( _boundResourceDefinitionType ) ? . GetType ( ) ;
40+ }
41+
42+ DiscoverImplementedHooks ( containerType ) ;
3543 }
3644
3745 /// <summary>
3846 /// Discovers the implemented hooks for a model.
3947 /// </summary>
4048 /// <returns>The implemented hooks for model.</returns>
41- void DiscoverImplementedHooksForModel ( )
49+ void DiscoverImplementedHooks ( Type containerType )
4250 {
43- Type parameterizedResourceDefinition = typeof ( ResourceDefinition < TResource > ) ;
44- var derivedTypes = TypeLocator . GetDerivedTypes ( typeof ( TResource ) . Assembly , parameterizedResourceDefinition ) . ToList ( ) ;
45-
46-
47- var implementedHooks = new List < ResourceHook > ( ) ;
48- var enabledHooks = new List < ResourceHook > ( ) { ResourceHook . BeforeImplicitUpdateRelationship } ;
49- var disabledHooks = new List < ResourceHook > ( ) ;
50- Type targetType = null ;
51- try
51+ if ( containerType == null || containerType == _boundResourceDefinitionType )
5252 {
53- targetType = derivedTypes . SingleOrDefault ( ) ; // multiple containers is not supported
53+ return ;
5454 }
55- catch
56- {
57- throw new JsonApiSetupException ( $ "It is currently not supported to" +
58- "implement hooks across multiple implementations of ResourceDefinition<T>" ) ;
59- }
60- if ( targetType != null )
55+
56+ var implementedHooks = new List < ResourceHook > ( ) ;
57+ // this hook can only be used with enabled database values
58+ var databaseValuesEnabledHooks = new List < ResourceHook > { ResourceHook . BeforeImplicitUpdateRelationship } ;
59+ var databaseValuesDisabledHooks = new List < ResourceHook > ( ) ;
60+ foreach ( var hook in _allHooks )
6161 {
62- foreach ( var hook in _allHooks )
62+ var method = containerType . GetMethod ( hook . ToString ( "G" ) ) ;
63+ if ( method . DeclaringType == _boundResourceDefinitionType )
64+ continue ;
65+
66+ implementedHooks . Add ( hook ) ;
67+ var attr = method . GetCustomAttributes ( true ) . OfType < LoadDatabaseValues > ( ) . SingleOrDefault ( ) ;
68+ if ( attr != null )
6369 {
64- var method = targetType . GetMethod ( hook . ToString ( "G" ) ) ;
65- if ( method . DeclaringType != parameterizedResourceDefinition )
70+ if ( ! _databaseValuesAttributeAllowed . Contains ( hook ) )
6671 {
67- implementedHooks . Add ( hook ) ;
68- var attr = method . GetCustomAttributes ( true ) . OfType < LoaDatabaseValues > ( ) . SingleOrDefault ( ) ;
69- if ( attr != null )
70- {
71- if ( ! _databaseValuesAttributeAllowed . Contains ( hook ) )
72- {
73- throw new JsonApiSetupException ( $ "DatabaseValuesAttribute cannot be used on hook" +
74- $ "{ hook . ToString ( "G" ) } in resource definition { parameterizedResourceDefinition . Name } ") ;
75- }
76- var targetList = attr . value ? enabledHooks : disabledHooks ;
77- targetList . Add ( hook ) ;
78- }
79- }
72+ throw new JsonApiSetupException ( $ "DatabaseValuesAttribute cannot be used on hook" +
73+ $ "{ hook . ToString ( "G" ) } in resource definition { containerType . Name } ") ;
74+ }
75+ var targetList = attr . value ? databaseValuesEnabledHooks : databaseValuesDisabledHooks ;
76+ targetList . Add ( hook ) ;
8077 }
81-
8278 }
83- ImplementedHooks = implementedHooks . ToArray ( ) ;
84- DatabaseValuesDisabledHooks = disabledHooks . ToArray ( ) ;
85- DatabaseValuesEnabledHooks = enabledHooks . ToArray ( ) ;
8679
80+ ImplementedHooks = implementedHooks . ToArray ( ) ;
81+ DatabaseValuesDisabledHooks = databaseValuesDisabledHooks . ToArray ( ) ;
82+ DatabaseValuesEnabledHooks = databaseValuesEnabledHooks . ToArray ( ) ;
8783 }
8884 }
89- }
85+ }
0 commit comments