Skip to content

Commit a11c9e9

Browse files
committed
chore: updated entity helpers
1 parent 0708c1c commit a11c9e9

File tree

10 files changed

+239
-80
lines changed

10 files changed

+239
-80
lines changed
Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Collections.ObjectModel;
45
using System.Linq;
56
using JsonApiDotNetCore.Internal;
67
using JsonApiDotNetCore.Models;
@@ -12,40 +13,38 @@ namespace JsonApiDotNetCore.Hooks
1213
/// Contains the resources from the request and the corresponding database values.
1314
///
1415
/// Also contains information about updated relationships through
15-
/// implementation of IRelationshipsDictionary<typeparamref name="TEntity"/>>
16+
/// implementation of IRelationshipsDictionary<typeparamref name="TResource"/>>
1617
/// </summary>
17-
public interface IEntityDiff<TEntity> : IExposeRelationshipsDictionary<TEntity>, IEnumerable<EntityDiffPair<TEntity>> where TEntity : class, IIdentifiable
18+
public interface IEntityDiffs<TResource> : IEnumerable<EntityDiffPair<TResource>> where TResource : class, IIdentifiable
1819
{
1920
/// <summary>
2021
/// The database values of the resources affected by the request.
2122
/// </summary>
22-
HashSet<TEntity> DatabaseValues { get; }
23+
HashSet<TResource> DatabaseValues { get; }
2324

2425
/// <summary>
2526
/// The resources that were affected by the request.
2627
/// </summary>
27-
HashSet<TEntity> Entities { get; }
28+
EntityHashSet<TResource> Entities { get; }
29+
2830
}
2931

3032
/// <inheritdoc />
31-
public class EntityDiffs<TEntity> : IEntityDiff<TEntity> where TEntity : class, IIdentifiable
33+
public class EntityDiffs<TResource> : IEntityDiffs<TResource> where TResource : class, IIdentifiable
3234
{
3335
/// <inheritdoc />
34-
public HashSet<TEntity> DatabaseValues { get => _databaseValues ?? ThrowNoDbValuesError(); }
35-
private readonly HashSet<TEntity> _databaseValues;
36-
private readonly bool _databaseValuesLoaded;
37-
38-
/// <inheritdoc />
39-
public HashSet<TEntity> Entities { get; private set; }
36+
public HashSet<TResource> DatabaseValues { get => _databaseValues ?? ThrowNoDbValuesError(); }
4037
/// <inheritdoc />
41-
public RelationshipsDictionary<TEntity> AffectedRelationships { get; private set; }
38+
public EntityHashSet<TResource> Entities { get; private set; }
4239

43-
public EntityDiffs(HashSet<TEntity> requestEntities,
44-
HashSet<TEntity> databaseEntities,
45-
Dictionary<RelationshipAttribute, HashSet<TEntity>> relationships)
40+
private readonly HashSet<TResource> _databaseValues;
41+
private readonly bool _databaseValuesLoaded;
42+
43+
public EntityDiffs(HashSet<TResource> requestEntities,
44+
HashSet<TResource> databaseEntities,
45+
Dictionary<RelationshipAttribute, HashSet<TResource>> relationships)
4646
{
47-
Entities = requestEntities;
48-
AffectedRelationships = new RelationshipsDictionary<TEntity>(relationships);
47+
Entities = new EntityHashSet<TResource>(requestEntities, relationships);
4948
_databaseValues = databaseEntities;
5049
_databaseValuesLoaded |= _databaseValues != null;
5150
}
@@ -56,38 +55,26 @@ public EntityDiffs(HashSet<TEntity> requestEntities,
5655
internal EntityDiffs(IEnumerable requestEntities,
5756
IEnumerable databaseEntities,
5857
Dictionary<RelationshipAttribute, IEnumerable> relationships)
59-
: this((HashSet<TEntity>)requestEntities, (HashSet<TEntity>)databaseEntities, TypeHelper.ConvertRelationshipDictionary<TEntity>(relationships)) { }
60-
58+
: this((HashSet<TResource>)requestEntities, (HashSet<TResource>)databaseEntities, TypeHelper.ConvertRelationshipDictionary<TResource>(relationships)) { }
6159

62-
/// <inheritdoc />
63-
public Dictionary<RelationshipAttribute, HashSet<TEntity>> GetByRelationship<TPrincipalResource>() where TPrincipalResource : class, IIdentifiable
64-
{
65-
return GetByRelationship(typeof(TPrincipalResource));
66-
}
67-
68-
/// <inheritdoc />
69-
public Dictionary<RelationshipAttribute, HashSet<TEntity>> GetByRelationship(Type principalType)
70-
{
71-
return AffectedRelationships.GetByRelationship(principalType);
72-
}
7360

7461
/// <inheritdoc />
75-
public IEnumerator<EntityDiffPair<TEntity>> GetEnumerator()
62+
public IEnumerator<EntityDiffPair<TResource>> GetEnumerator()
7663
{
7764
if (!_databaseValuesLoaded) ThrowNoDbValuesError();
7865

7966
foreach (var entity in Entities)
8067
{
81-
TEntity currentValueInDatabase = null;
68+
TResource currentValueInDatabase = null;
8269
currentValueInDatabase = _databaseValues.Single(e => entity.StringId == e.StringId);
83-
yield return new EntityDiffPair<TEntity>(entity, currentValueInDatabase);
70+
yield return new EntityDiffPair<TResource>(entity, currentValueInDatabase);
8471
}
8572
}
8673

8774
/// <inheritdoc />
8875
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
8976

90-
private HashSet<TEntity> ThrowNoDbValuesError()
77+
private HashSet<TResource> ThrowNoDbValuesError()
9178
{
9279
throw new MemberAccessException("Cannot access database entities if the LoadDatabaseValues option is set to false");
9380
}
@@ -97,9 +84,9 @@ private HashSet<TEntity> ThrowNoDbValuesError()
9784
/// A wrapper that contains an entity that is affected by the request,
9885
/// matched to its current database value
9986
/// </summary>
100-
public class EntityDiffPair<TEntity> where TEntity : class, IIdentifiable
87+
public class EntityDiffPair<TResource> where TResource : class, IIdentifiable
10188
{
102-
public EntityDiffPair(TEntity entity, TEntity databaseValue)
89+
public EntityDiffPair(TResource entity, TResource databaseValue)
10390
{
10491
Entity = entity;
10592
DatabaseValue = databaseValue;
@@ -108,10 +95,10 @@ public EntityDiffPair(TEntity entity, TEntity databaseValue)
10895
/// <summary>
10996
/// The resource from the request matching the resource from the database.
11097
/// </summary>
111-
public TEntity Entity { get; private set; }
98+
public TResource Entity { get; private set; }
11299
/// <summary>
113100
/// The resource from the database matching the resource from the request.
114101
/// </summary>
115-
public TEntity DatabaseValue { get; private set; }
102+
public TResource DatabaseValue { get; private set; }
116103
}
117104
}

src/JsonApiDotNetCore/Hooks/Execution/EntityHashSet.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.Collections;
44
using JsonApiDotNetCore.Internal;
55
using System;
6+
using System.Collections.ObjectModel;
7+
using System.Collections.Immutable;
68

79
namespace JsonApiDotNetCore.Hooks
810
{
@@ -12,7 +14,7 @@ namespace JsonApiDotNetCore.Hooks
1214
/// Also contains information about updated relationships through
1315
/// implementation of IAffectedRelationshipsDictionary<typeparamref name="TResource"/>>
1416
/// </summary>
15-
public interface IEntityHashSet<TResource> : IExposeRelationshipsDictionary<TResource>, IEnumerable<TResource> where TResource : class, IIdentifiable { }
17+
public interface IEntityHashSet<TResource> : IByAffectedRelationships<TResource>, IReadOnlyCollection<TResource> where TResource : class, IIdentifiable { }
1618

1719
/// <summary>
1820
/// Implementation of IResourceHashSet{TResource}.
@@ -24,13 +26,16 @@ public interface IEntityHashSet<TResource> : IExposeRelationshipsDictionary<TRes
2426
/// </summary>
2527
public class EntityHashSet<TResource> : HashSet<TResource>, IEntityHashSet<TResource> where TResource : class, IIdentifiable
2628
{
29+
30+
2731
/// <inheritdoc />
28-
public RelationshipsDictionary<TResource> AffectedRelationships { get; private set; }
32+
public Dictionary<RelationshipAttribute, HashSet<TResource>> AffectedRelationships { get => _relationships; }
33+
private readonly RelationshipsDictionary<TResource> _relationships;
2934

3035
public EntityHashSet(HashSet<TResource> entities,
3136
Dictionary<RelationshipAttribute, HashSet<TResource>> relationships) : base(entities)
3237
{
33-
AffectedRelationships = new RelationshipsDictionary<TResource>(relationships);
38+
_relationships = new RelationshipsDictionary<TResource>(relationships);
3439
}
3540

3641
/// <summary>
@@ -44,13 +49,13 @@ internal EntityHashSet(IEnumerable entities,
4449
/// <inheritdoc />
4550
public Dictionary<RelationshipAttribute, HashSet<TResource>> GetByRelationship(Type principalType)
4651
{
47-
return AffectedRelationships.GetByRelationship(principalType);
52+
return _relationships.GetByRelationship(principalType);
4853
}
4954

5055
/// <inheritdoc />
51-
public Dictionary<RelationshipAttribute, HashSet<TResource>> GetByRelationship<TPrincipalResource>() where TPrincipalResource : class, IIdentifiable
56+
public Dictionary<RelationshipAttribute, HashSet<TResource>> GetByRelationship<TRelatedResource>() where TRelatedResource : class, IIdentifiable
5257
{
53-
return GetByRelationship<TPrincipalResource>();
58+
return GetByRelationship(typeof(TRelatedResource));
5459
}
5560
}
5661
}
Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,45 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4-
using System.Collections.ObjectModel;
54
using System.Linq;
65
using JsonApiDotNetCore.Internal;
76
using JsonApiDotNetCore.Models;
87

98
namespace JsonApiDotNetCore.Hooks
109
{
10+
11+
12+
13+
/// <summary>
14+
/// A dummy interface used internally by the hook executor.
15+
/// </summary>
1116
public interface IRelationshipsDictionary { }
1217

18+
1319
/// <summary>
1420
/// An interface that is implemented to expose a relationship dictionary on another class.
1521
/// </summary>
16-
public interface IExposeRelationshipsDictionary<TDependentResource> :
17-
IRelationshipsDictionaryGetters<TDependentResource> where TDependentResource : class, IIdentifiable
22+
public interface IByAffectedRelationships<TDependentResource> :
23+
IRelationshipGetters<TDependentResource> where TDependentResource : class, IIdentifiable
1824
{
1925
/// <summary>
2026
/// Gets a dictionary of affected resources grouped by affected relationships.
2127
/// </summary>
22-
RelationshipsDictionary<TDependentResource> AffectedRelationships { get; }
28+
Dictionary<RelationshipAttribute, HashSet<TDependentResource>> AffectedRelationships { get; }
2329
}
2430

2531
/// <summary>
2632
/// A helper class that provides insights in which relationships have been updated for which entities.
2733
/// </summary>
2834
public interface IRelationshipsDictionary<TDependentResource> :
29-
IRelationshipsDictionaryGetters<TDependentResource>,
35+
IRelationshipGetters<TDependentResource>,
3036
IReadOnlyDictionary<RelationshipAttribute, HashSet<TDependentResource>>,
3137
IRelationshipsDictionary where TDependentResource : class, IIdentifiable { }
3238

3339
/// <summary>
3440
/// A helper class that provides insights in which relationships have been updated for which entities.
3541
/// </summary>
36-
public interface IRelationshipsDictionaryGetters<TDependentResource> where TDependentResource : class, IIdentifiable
42+
public interface IRelationshipGetters<TDependentResource> where TDependentResource : class, IIdentifiable
3743
{
3844
/// <summary>
3945
/// Gets a dictionary of all entities that have an affected relationship to type <typeparamref name="TPrincipalResource"/>
@@ -51,38 +57,32 @@ public interface IRelationshipsDictionaryGetters<TDependentResource> where TDepe
5157
/// It is practically a ReadOnlyDictionary{RelationshipAttribute, HashSet{TDependentResource}} dictionary
5258
/// with the two helper methods defined on IAffectedRelationships{TDependentResource}.
5359
/// </summary>
54-
public class RelationshipsDictionary<TDependentResource> :
55-
ReadOnlyDictionary<RelationshipAttribute, HashSet<TDependentResource>>,
56-
IRelationshipsDictionary<TDependentResource> where TDependentResource : class, IIdentifiable
60+
public class RelationshipsDictionary<TResource> :
61+
Dictionary<RelationshipAttribute, HashSet<TResource>>,
62+
IRelationshipsDictionary<TResource> where TResource : class, IIdentifiable
5763
{
5864
/// <summary>
59-
/// a dictionary with affected relationships as keys and values being the corresponding resources
60-
/// that were affected
65+
/// Initializes a new instance of the <see cref="T:JsonApiDotNetCore.Hooks.RelationshipsDictionary`1"/> class.
6166
/// </summary>
62-
private readonly Dictionary<RelationshipAttribute, HashSet<TDependentResource>> _groups;
63-
64-
/// <inheritdoc />
65-
public RelationshipsDictionary(Dictionary<RelationshipAttribute, HashSet<TDependentResource>> relationships) : base(relationships)
66-
{
67-
_groups = relationships;
68-
}
67+
/// <param name="relationships">Relationships.</param>
68+
public RelationshipsDictionary(Dictionary<RelationshipAttribute, HashSet<TResource>> relationships) : base(relationships) { }
6969

7070
/// <summary>
7171
/// Used internally by the ResourceHookExecutor to make live a bit easier with generics
7272
/// </summary>
7373
internal RelationshipsDictionary(Dictionary<RelationshipAttribute, IEnumerable> relationships)
74-
: this(TypeHelper.ConvertRelationshipDictionary<TDependentResource>(relationships)) { }
74+
: this(TypeHelper.ConvertRelationshipDictionary<TResource>(relationships)) { }
7575

7676
/// <inheritdoc />
77-
public Dictionary<RelationshipAttribute, HashSet<TDependentResource>> GetByRelationship<TPrincipalResource>() where TPrincipalResource : class, IIdentifiable
77+
public Dictionary<RelationshipAttribute, HashSet<TResource>> GetByRelationship<TRelatedResource>() where TRelatedResource : class, IIdentifiable
7878
{
79-
return GetByRelationship(typeof(TPrincipalResource));
79+
return GetByRelationship(typeof(TRelatedResource));
8080
}
8181

8282
/// <inheritdoc />
83-
public Dictionary<RelationshipAttribute, HashSet<TDependentResource>> GetByRelationship(Type principalType)
83+
public Dictionary<RelationshipAttribute, HashSet<TResource>> GetByRelationship(Type relatedType)
8484
{
85-
return this.Where(p => p.Key.PrincipalType == principalType).ToDictionary(p => p.Key, p => p.Value);
85+
return this.Where(p => p.Key.PrincipalType == relatedType).ToDictionary(p => p.Key, p => p.Value);
8686
}
8787
}
8888
}

src/JsonApiDotNetCore/Hooks/IResourceHookContainer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public interface IBeforeHooks<TResource> where TResource : class, IIdentifiable
7777
/// <returns>The transformed entity set</returns>
7878
/// <param name="entityDiff">The entity diff.</param>
7979
/// <param name="pipeline">An enum indicating from where the hook was triggered.</param>
80-
IEnumerable<TResource> BeforeUpdate(IEntityDiff<TResource> entityDiff, ResourcePipeline pipeline);
80+
IEnumerable<TResource> BeforeUpdate(IEntityDiffs<TResource> entityDiff, ResourcePipeline pipeline);
8181

8282
/// <summary>
8383
/// Implement this hook to run custom logic in the <see cref=" EntityResourceService{T}"/>

src/JsonApiDotNetCore/Internal/TypeHelper.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Linq;
55
using System.Reflection;
6+
using JsonApiDotNetCore.Hooks;
67
using JsonApiDotNetCore.Models;
78

89
namespace JsonApiDotNetCore.Internal
@@ -113,9 +114,9 @@ public static object CreateInstanceOfOpenType(Type openType, Type[] parameters,
113114
/// <summary>
114115
/// Helper method that "unboxes" the TValue from the relationship dictionary into
115116
/// </summary>
116-
public static Dictionary<RelationshipAttribute, HashSet<TDependentResource>> ConvertRelationshipDictionary<TDependentResource>(Dictionary<RelationshipAttribute, IEnumerable> relationships)
117+
public static Dictionary<RelationshipAttribute, HashSet<TValueOut>> ConvertRelationshipDictionary<TValueOut>(Dictionary<RelationshipAttribute, IEnumerable> relationships)
117118
{
118-
return relationships.ToDictionary(pair => pair.Key, pair => (HashSet<TDependentResource>)pair.Value);
119+
return relationships.ToDictionary(pair => pair.Key, pair => (HashSet<TValueOut>)pair.Value);
119120
}
120121

121122
/// <summary>

src/JsonApiDotNetCore/Models/ResourceDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public virtual void AfterUpdateRelationship(IRelationshipsDictionary<T> entities
179179
/// <inheritdoc/>
180180
public virtual void BeforeRead(ResourcePipeline pipeline, bool isIncluded = false, string stringId = null) { }
181181
/// <inheritdoc/>
182-
public virtual IEnumerable<T> BeforeUpdate(IEntityDiff<T> entityDiff, ResourcePipeline pipeline) { return entityDiff.Entities; }
182+
public virtual IEnumerable<T> BeforeUpdate(IEntityDiffs<T> entityDiff, ResourcePipeline pipeline) { return entityDiff.Entities; }
183183
/// <inheritdoc/>
184184
public virtual IEnumerable<T> BeforeDelete(IEntityHashSet<T> entities, ResourcePipeline pipeline) { return entities; }
185185
/// <inheritdoc/>

0 commit comments

Comments
 (0)