Skip to content

Commit 8a9056b

Browse files
committed
feat: hook resource helpers that feel more intuitive
1 parent 9935a86 commit 8a9056b

File tree

15 files changed

+61
-58
lines changed

15 files changed

+61
-58
lines changed

src/Examples/JsonApiDotNetCoreExample/Resources/TagResource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public TagResource(IResourceGraph graph) : base(graph)
1313
{
1414
}
1515

16-
public override IEnumerable<Tag> BeforeCreate(IAffectedResources<Tag> affected, ResourcePipeline pipeline)
16+
public override IEnumerable<Tag> BeforeCreate(IResourceHashSet<Tag> affected, ResourcePipeline pipeline)
1717
{
1818
return base.BeforeCreate(affected, pipeline);
1919
}

src/JsonApiDotNetCore/Hooks/Execution/RelationshipsDictionary.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
namespace JsonApiDotNetCore.Hooks
1010
{
11-
public interface IAffectedRelationships { }
11+
public interface IRelationshipsDictionary { }
1212

1313
/// <summary>
1414
/// An interface that is implemented to expose a relationship dictionary on another class.
1515
/// </summary>
16-
public interface IRelationshipsDictionary<TDependentResource> : IRelationshipsDictionaryGetters<TDependentResource> where TDependentResource : class, IIdentifiable
16+
public interface IExposeRelationshipsDictionary<TDependentResource> : IRelationshipsDictionary<TDependentResource> where TDependentResource : class, IIdentifiable
1717
{
1818
/// <summary>
1919
/// Gets a dictionary of affected resources grouped by affected relationships.
@@ -24,7 +24,7 @@ public interface IRelationshipsDictionary<TDependentResource> : IRelationshipsDi
2424
/// <summary>
2525
/// A helper class that provides insights in which relationships have been updated for which entities.
2626
/// </summary>
27-
public interface IRelationshipsDictionaryGetters<TDependentResource> : IAffectedRelationships where TDependentResource : class, IIdentifiable
27+
public interface IRelationshipsDictionary<TDependentResource> : IRelationshipsDictionary where TDependentResource : class, IIdentifiable
2828
{
2929
/// <summary>
3030
/// Gets a dictionary of all entities that have an affected relationship to type <typeparamref name="TPrincipalResource"/>
@@ -42,7 +42,7 @@ public interface IRelationshipsDictionaryGetters<TDependentResource> : IAffected
4242
/// It is practically a ReadOnlyDictionary{RelationshipAttribute, HashSet{TDependentResource}} dictionary
4343
/// with the two helper methods defined on IAffectedRelationships{TDependentResource}.
4444
/// </summary>
45-
public class RelationshipsDictionary<TDependentResource> : ReadOnlyDictionary<RelationshipAttribute, HashSet<TDependentResource>>, IRelationshipsDictionaryGetters<TDependentResource> where TDependentResource : class, IIdentifiable
45+
public class RelationshipsDictionary<TDependentResource> : ReadOnlyDictionary<RelationshipAttribute, HashSet<TDependentResource>>, IRelationshipsDictionary<TDependentResource> where TDependentResource : class, IIdentifiable
4646
{
4747
/// <summary>
4848
/// a dictionary with affected relationships as keys and values being the corresponding resources

src/JsonApiDotNetCore/Hooks/Execution/AffectedResourcesDiffs.cs renamed to src/JsonApiDotNetCore/Hooks/Execution/ResourceDiffs.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ namespace JsonApiDotNetCore.Hooks
1212
/// Contains the resources from the request and the corresponding database values.
1313
///
1414
/// Also contains information about updated relationships through
15-
/// implementation of IAffectedRelationshipsDictionary<typeparamref name="TResource"/>>
15+
/// implementation of IRelationshipsDictionary<typeparamref name="TResource"/>>
1616
/// </summary>
17-
public interface IAffectedResourcesDiffs<TResource> : IRelationshipsDictionary<TResource>, IEnumerable<ResourceDiffPair<TResource>> where TResource : class, IIdentifiable
17+
public interface IResourceDiffs<TResource> : IRelationshipsDictionary<TResource>, IEnumerable<ResourceDiffPair<TResource>> where TResource : class, IIdentifiable
1818
{
1919
/// <summary>
2020
/// The database values of the resources affected by the request.
@@ -28,19 +28,19 @@ public interface IAffectedResourcesDiffs<TResource> : IRelationshipsDictionary<T
2828
}
2929

3030
/// <inheritdoc />
31-
public class AffectedResourcesDiffs<TResource> : IAffectedResourcesDiffs<TResource> where TResource : class, IIdentifiable
31+
public class ResourceDiffs<TResource> : IResourceDiffs<TResource> where TResource : class, IIdentifiable
3232
{
33+
/// <inheritdoc />
34+
public HashSet<TResource> DatabaseValues { get => _databaseValues ?? ThrowNoDbValuesError(); }
3335
private readonly HashSet<TResource> _databaseValues;
3436
private readonly bool _databaseValuesLoaded;
3537

36-
/// <inheritdoc />
37-
public HashSet<TResource> DatabaseValues { get => _databaseValues ?? ThrowNoDbValuesError(); }
3838
/// <inheritdoc />
3939
public HashSet<TResource> Resources { get; private set; }
4040
/// <inheritdoc />
4141
public RelationshipsDictionary<TResource> AffectedRelationships { get; private set; }
4242

43-
public AffectedResourcesDiffs(HashSet<TResource> requestEntities,
43+
public ResourceDiffs(HashSet<TResource> requestEntities,
4444
HashSet<TResource> databaseEntities,
4545
Dictionary<RelationshipAttribute, HashSet<TResource>> relationships)
4646
{
@@ -53,7 +53,7 @@ public AffectedResourcesDiffs(HashSet<TResource> requestEntities,
5353
/// <summary>
5454
/// Used internally by the ResourceHookExecutor to make live a bit easier with generics
5555
/// </summary>
56-
internal AffectedResourcesDiffs(IEnumerable requestEntities,
56+
internal ResourceDiffs(IEnumerable requestEntities,
5757
IEnumerable databaseEntities,
5858
Dictionary<RelationshipAttribute, IEnumerable> relationships)
5959
: this((HashSet<TResource>)requestEntities, (HashSet<TResource>)databaseEntities, TypeHelper.ConvertRelationshipDictionary<TResource>(relationships)) { }

src/JsonApiDotNetCore/Hooks/Execution/AffectedResources.cs renamed to src/JsonApiDotNetCore/Hooks/Execution/ResourceHashSet.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,25 @@ namespace JsonApiDotNetCore.Hooks
1313
/// Also contains information about updated relationships through
1414
/// implementation of IAffectedRelationshipsDictionary<typeparamref name="TResource"/>>
1515
/// </summary>
16-
public interface IAffectedResources<TResource> : IRelationshipsDictionary<TResource>, IEnumerable<TResource> where TResource : class, IIdentifiable
16+
public interface IResourceHashSet<TResource> : IRelationshipsDictionary<TResource>, IEnumerable<TResource> where TResource : class, IIdentifiable
1717
{
1818

1919
}
2020

2121
/// <summary>
22-
/// Implementation of IAffectedResources{TResource}.
22+
/// Implementation of IResourceHashSet{TResource}.
2323
///
24-
/// It is basically just a HashSet{TResource} that also stores the
25-
/// RelationshipDictionary{TResource} and the same helper methods to access this
26-
/// dictionary as defined on IAffectedRelationshipsDictionary{TResource}.
24+
/// Basically a enumerable of <typeparamref name="TResource"/> of resources that were affected by the request.
25+
///
26+
/// Also contains information about updated relationships through
27+
/// implementation of IRelationshipsDictionary<typeparamref name="TResource"/>>
2728
/// </summary>
28-
public class AffectedResources<TResource> : HashSet<TResource>, IAffectedResources<TResource> where TResource : class, IIdentifiable
29+
public class ResourceHashSet<TResource> : HashSet<TResource>, IResourceHashSet<TResource> where TResource : class, IIdentifiable
2930
{
3031
/// <inheritdoc />
3132
public RelationshipsDictionary<TResource> AffectedRelationships { get; private set; }
3233

33-
public AffectedResources(HashSet<TResource> entities,
34+
public ResourceHashSet(HashSet<TResource> entities,
3435
Dictionary<RelationshipAttribute, HashSet<TResource>> relationships) : base(entities)
3536
{
3637
AffectedRelationships = new RelationshipsDictionary<TResource>(relationships);
@@ -39,16 +40,18 @@ public AffectedResources(HashSet<TResource> entities,
3940
/// <summary>
4041
/// Used internally by the ResourceHookExecutor to make live a bit easier with generics
4142
/// </summary>
42-
internal AffectedResources(IEnumerable entities,
43+
internal ResourceHashSet(IEnumerable entities,
4344
Dictionary<RelationshipAttribute, IEnumerable> relationships)
4445
: this((HashSet<TResource>)entities, TypeHelper.ConvertRelationshipDictionary<TResource>(relationships)) { }
4546

4647

48+
/// <inheritdoc />
4749
public Dictionary<RelationshipAttribute, HashSet<TResource>> GetByRelationship(Type principalType)
4850
{
4951
return AffectedRelationships.GetByRelationship(principalType);
5052
}
5153

54+
/// <inheritdoc />
5255
public Dictionary<RelationshipAttribute, HashSet<TResource>> GetByRelationship<TPrincipalResource>() where TPrincipalResource : class, IIdentifiable
5356
{
5457
return GetByRelationship<TPrincipalResource>();

src/JsonApiDotNetCore/Hooks/IResourceHookContainer.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public interface IBeforeHooks<TEntity> where TEntity : class, IIdentifiable
4141
/// <returns>The transformed entity set</returns>
4242
/// <param name="entities">The unique set of affected entities.</param>
4343
/// <param name="pipeline">An enum indicating from where the hook was triggered.</param>
44-
IEnumerable<TEntity> BeforeCreate(IAffectedResources<TEntity> entities, ResourcePipeline pipeline);
44+
IEnumerable<TEntity> BeforeCreate(IResourceHashSet<TEntity> entities, ResourcePipeline pipeline);
4545
/// <summary>
4646
/// Implement this hook to run custom logic in the <see cref=" EntityResourceService{T}"/>
4747
/// layer just before reading entities of type <typeparamref name="TEntity"/>.
@@ -60,7 +60,7 @@ public interface IBeforeHooks<TEntity> where TEntity : class, IIdentifiable
6060
/// multiple entities.
6161
/// <para />
6262
/// The returned <see cref="IEnumerable{TEntity}"/> may be a subset
63-
/// of the <see cref="AffectedResourcesDiffs{TEntity}.RequestEntities"/> property in parameter <paramref name="ResourceDiff"/>,
63+
/// of the <see cref="ResourceDiffs{TEntity}.RequestEntities"/> property in parameter <paramref name="ResourceDiff"/>,
6464
/// in which case the operation of the pipeline will not be executed
6565
/// for the omitted entities. The returned set may also contain custom
6666
/// changes of the properties on the entities.
@@ -78,7 +78,7 @@ public interface IBeforeHooks<TEntity> where TEntity : class, IIdentifiable
7878
/// <returns>The transformed entity set</returns>
7979
/// <param name="ResourceDiff">The entity diff.</param>
8080
/// <param name="pipeline">An enum indicating from where the hook was triggered.</param>
81-
IEnumerable<TEntity> BeforeUpdate(IAffectedResourcesDiffs<TEntity> ResourceDiff, ResourcePipeline pipeline);
81+
IEnumerable<TEntity> BeforeUpdate(IResourceDiffs<TEntity> ResourceDiff, ResourcePipeline pipeline);
8282

8383
/// <summary>
8484
/// Implement this hook to run custom logic in the <see cref=" EntityResourceService{T}"/>
@@ -101,7 +101,7 @@ public interface IBeforeHooks<TEntity> where TEntity : class, IIdentifiable
101101
/// <returns>The transformed entity set</returns>
102102
/// <param name="entities">The unique set of affected entities.</param>
103103
/// <param name="pipeline">An enum indicating from where the hook was triggered.</param>
104-
IEnumerable<TEntity> BeforeDelete(IAffectedResources<TEntity> entities, ResourcePipeline pipeline);
104+
IEnumerable<TEntity> BeforeDelete(IResourceHashSet<TEntity> entities, ResourcePipeline pipeline);
105105
/// <summary>
106106
/// Implement this hook to run custom logic in the <see cref=" EntityResourceService{T}"/>
107107
/// layer just before updating relationships to entities of type <typeparamref name="TEntity"/>.

src/JsonApiDotNetCore/Hooks/ResourceHookExecutor.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public virtual IEnumerable<TEntity> BeforeUpdate<TEntity>(IEnumerable<TEntity> e
4949
{
5050
var relationships = node.RelationshipsToNextLayer.Select(p => p.Attribute).ToArray();
5151
var dbValues = LoadDbValues(typeof(TEntity), (IEnumerable<TEntity>)node.UniqueEntities, ResourceHook.BeforeUpdate, relationships);
52-
var diff = new AffectedResourcesDiffs<TEntity>(node.UniqueEntities, dbValues, node.PrincipalsToNextLayer());
52+
var diff = new ResourceDiffs<TEntity>(node.UniqueEntities, dbValues, node.PrincipalsToNextLayer());
5353
IEnumerable<TEntity> updated = container.BeforeUpdate(diff, pipeline);
5454
node.UpdateUnique(updated);
5555
node.Reassign(entities);
@@ -65,7 +65,7 @@ public virtual IEnumerable<TEntity> BeforeCreate<TEntity>(IEnumerable<TEntity> e
6565
{
6666
if (GetHook(ResourceHook.BeforeCreate, entities, out var container, out var node))
6767
{
68-
var affected = new AffectedResources<TEntity>((HashSet<TEntity>)node.UniqueEntities, node.PrincipalsToNextLayer());
68+
var affected = new ResourceHashSet<TEntity>((HashSet<TEntity>)node.UniqueEntities, node.PrincipalsToNextLayer());
6969
IEnumerable<TEntity> updated = container.BeforeCreate(affected, pipeline);
7070
node.UpdateUnique(updated);
7171
node.Reassign(entities);
@@ -82,7 +82,7 @@ public virtual IEnumerable<TEntity> BeforeDelete<TEntity>(IEnumerable<TEntity> e
8282
{
8383
var relationships = node.RelationshipsToNextLayer.Select(p => p.Attribute).ToArray();
8484
var targetEntities = LoadDbValues(typeof(TEntity), (IEnumerable<TEntity>)node.UniqueEntities, ResourceHook.BeforeDelete, relationships) ?? node.UniqueEntities;
85-
var affected = new AffectedResources<TEntity>(targetEntities, node.PrincipalsToNextLayer());
85+
var affected = new ResourceHashSet<TEntity>(targetEntities, node.PrincipalsToNextLayer());
8686

8787
IEnumerable<TEntity> updated = container.BeforeDelete(affected, pipeline);
8888
node.UpdateUnique(updated);
@@ -353,10 +353,10 @@ object ThrowJsonApiExceptionOnError(Func<object> action)
353353
/// If <paramref name="dbValues"/> are included, the values of the entries in <paramref name="prevLayerRelationships"/> need to be replaced with these values.
354354
/// </summary>
355355
/// <returns>The relationship helper.</returns>
356-
IAffectedRelationships CreateRelationshipHelper(DependentType entityType, Dictionary<RelationshipAttribute, IEnumerable> prevLayerRelationships, IEnumerable dbValues = null)
356+
IRelationshipsDictionary CreateRelationshipHelper(DependentType entityType, Dictionary<RelationshipAttribute, IEnumerable> prevLayerRelationships, IEnumerable dbValues = null)
357357
{
358358
if (dbValues != null) prevLayerRelationships = ReplaceWithDbValues(prevLayerRelationships, dbValues.Cast<IIdentifiable>());
359-
return (IAffectedRelationships)TypeHelper.CreateInstanceOfOpenType(typeof(RelationshipsDictionary<>), entityType, true, prevLayerRelationships);
359+
return (IRelationshipsDictionary)TypeHelper.CreateInstanceOfOpenType(typeof(RelationshipsDictionary<>), entityType, true, prevLayerRelationships);
360360
}
361361

362362
/// <summary>

src/JsonApiDotNetCore/Models/ResourceDefinition.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,13 @@ public virtual void AfterDelete(HashSet<T> entities, ResourcePipeline pipeline,
175175
/// <inheritdoc/>
176176
public virtual void AfterUpdateRelationship(IRelationshipsDictionary<T> resourcesByRelationship, ResourcePipeline pipeline) { }
177177
/// <inheritdoc/>
178-
public virtual IEnumerable<T> BeforeCreate(IAffectedResources<T> affected, ResourcePipeline pipeline) { return affected; }
178+
public virtual IEnumerable<T> BeforeCreate(IResourceHashSet<T> affected, ResourcePipeline pipeline) { return affected; }
179179
/// <inheritdoc/>
180180
public virtual void BeforeRead(ResourcePipeline pipeline, bool isIncluded = false, string stringId = null) { }
181181
/// <inheritdoc/>
182-
public virtual IEnumerable<T> BeforeUpdate(IAffectedResourcesDiffs<T> ResourceDiff, ResourcePipeline pipeline) { return ResourceDiff.Resources; }
182+
public virtual IEnumerable<T> BeforeUpdate(IResourceDiffs<T> ResourceDiff, ResourcePipeline pipeline) { return ResourceDiff.Resources; }
183183
/// <inheritdoc/>
184-
public virtual IEnumerable<T> BeforeDelete(IAffectedResources<T> affected, ResourcePipeline pipeline) { return affected; }
184+
public virtual IEnumerable<T> BeforeDelete(IResourceHashSet<T> affected, ResourcePipeline pipeline) { return affected; }
185185
/// <inheritdoc/>
186186
public virtual IEnumerable<string> BeforeUpdateRelationship(HashSet<string> ids, IRelationshipsDictionary<T> resourcesByRelationship, ResourcePipeline pipeline) { return ids; }
187187
/// <inheritdoc/>

test/UnitTests/ResourceHooks/DiscoveryTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class DummyResourceDefinition : ResourceDefinition<Dummy>
1414
{
1515
public DummyResourceDefinition() : base(new ResourceGraphBuilder().AddResource<Dummy>().Build()) { }
1616

17-
public override IEnumerable<Dummy> BeforeDelete(IAffectedResources<Dummy> affected, ResourcePipeline pipeline) { return affected; }
17+
public override IEnumerable<Dummy> BeforeDelete(IResourceHashSet<Dummy> affected, ResourcePipeline pipeline) { return affected; }
1818
public override void AfterDelete(HashSet<Dummy> entities, ResourcePipeline pipeline, bool succeeded) { }
1919
}
2020

@@ -35,7 +35,7 @@ public abstract class ResourceDefintionBase<T> : ResourceDefinition<T> where T :
3535
{
3636
protected ResourceDefintionBase(IResourceGraph graph) : base(graph) { }
3737

38-
public override IEnumerable<T> BeforeDelete(IAffectedResources<T> affected, ResourcePipeline pipeline) { return affected; }
38+
public override IEnumerable<T> BeforeDelete(IResourceHashSet<T> affected, ResourcePipeline pipeline) { return affected; }
3939
public override void AfterDelete(HashSet<T> entities, ResourcePipeline pipeline, bool succeeded) { }
4040
}
4141

@@ -59,7 +59,7 @@ public class YetAnotherDummyResourceDefinition : ResourceDefinition<YetAnotherDu
5959
{
6060
public YetAnotherDummyResourceDefinition() : base(new ResourceGraphBuilder().AddResource<YetAnotherDummy>().Build()) { }
6161

62-
public override IEnumerable<YetAnotherDummy> BeforeDelete(IAffectedResources<YetAnotherDummy> affected, ResourcePipeline pipeline) { return affected; }
62+
public override IEnumerable<YetAnotherDummy> BeforeDelete(IResourceHashSet<YetAnotherDummy> affected, ResourcePipeline pipeline) { return affected; }
6363

6464
[LoadDatabaseValues(false)]
6565
public override void AfterDelete(HashSet<YetAnotherDummy> entities, ResourcePipeline pipeline, bool succeeded) { }
@@ -81,7 +81,7 @@ public class DoubleDummyResourceDefinition1 : ResourceDefinition<DoubleDummy>
8181
{
8282
public DoubleDummyResourceDefinition1() : base(new ResourceGraphBuilder().AddResource<DoubleDummy>().Build()) { }
8383

84-
public override IEnumerable<DoubleDummy> BeforeDelete(IAffectedResources<DoubleDummy> affected, ResourcePipeline pipeline) { return affected; }
84+
public override IEnumerable<DoubleDummy> BeforeDelete(IResourceHashSet<DoubleDummy> affected, ResourcePipeline pipeline) { return affected; }
8585
}
8686
public class DoubleDummyResourceDefinition2 : ResourceDefinition<DoubleDummy>
8787
{

0 commit comments

Comments
 (0)