Skip to content

Commit 606f627

Browse files
author
Bart Koelman
committed
More fixes for resources with parameterized constructors
1 parent 04aff35 commit 606f627

File tree

18 files changed

+70
-56
lines changed

18 files changed

+70
-56
lines changed

src/Examples/JsonApiDotNetCoreExample/Models/ArticleTag.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
using System;
12
using JsonApiDotNetCore.Models;
3+
using JsonApiDotNetCoreExample.Data;
24

35
namespace JsonApiDotNetCoreExample.Models
46
{
@@ -9,8 +11,12 @@ public sealed class ArticleTag
911

1012
public int TagId { get; set; }
1113
public Tag Tag { get; set; }
12-
}
1314

15+
public ArticleTag(AppDbContext appDbContext)
16+
{
17+
if (appDbContext == null) throw new ArgumentNullException(nameof(appDbContext));
18+
}
19+
}
1420

1521
public class IdentifiableArticleTag : Identifiable
1622
{

src/JsonApiDotNetCore/Data/DefaultResourceRepository.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public virtual async Task CreateAsync(TResource entity)
109109
// was already tracked) than the one assigned to the to-be-created entity.
110110
// Alternatively, even if we don't have to reassign anything because of already tracked
111111
// entities, we still need to assign the "through" entities in the case of many-to-many.
112-
relationshipAttr.SetValue(entity, trackedRelationshipValue);
112+
relationshipAttr.SetValue(entity, trackedRelationshipValue, _resourceFactory);
113113
}
114114
_dbSet.Add(entity);
115115
await _context.SaveChangesAsync();
@@ -182,7 +182,7 @@ private void DetachRelationships(TResource entity)
182182
// trigger a full reload of relationships: the navigation
183183
// property actually needs to be nulled out, otherwise
184184
// EF will still add duplicate instances to the collection
185-
relationship.SetValue(entity, null);
185+
relationship.SetValue(entity, null, _resourceFactory);
186186
}
187187
else
188188
{
@@ -216,7 +216,7 @@ public virtual async Task UpdateAsync(TResource requestEntity, TResource databas
216216
LoadInverseRelationships(trackedRelationshipValue, relationshipAttr);
217217
// assigns the updated relationship to the database entity
218218
//AssignRelationshipValue(databaseEntity, trackedRelationshipValue, relationshipAttr);
219-
relationshipAttr.SetValue(databaseEntity, trackedRelationshipValue);
219+
relationshipAttr.SetValue(databaseEntity, trackedRelationshipValue, _resourceFactory);
220220
}
221221

222222
await _context.SaveChangesAsync();

src/JsonApiDotNetCore/Hooks/ResourceHookExecutor.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@ internal sealed class ResourceHookExecutor : IResourceHookExecutor
2222
private readonly IIncludeService _includeService;
2323
private readonly ITargetedFields _targetedFields;
2424
private readonly IResourceGraph _resourceGraph;
25+
private readonly IResourceFactory _resourceFactory;
2526

2627
public ResourceHookExecutor(
2728
IHookExecutorHelper executorHelper,
2829
ITraversalHelper traversalHelper,
2930
ITargetedFields targetedFields,
3031
IIncludeService includedRelationships,
31-
IResourceGraph resourceGraph)
32+
IResourceGraph resourceGraph,
33+
IResourceFactory resourceFactory)
3234
{
3335
_executorHelper = executorHelper;
3436
_traversalHelper = traversalHelper;
3537
_targetedFields = targetedFields;
3638
_includeService = includedRelationships;
3739
_resourceGraph = resourceGraph;
40+
_resourceFactory = resourceFactory;
3841
}
3942

4043
/// <inheritdoc/>
@@ -57,7 +60,7 @@ public IEnumerable<TResource> BeforeUpdate<TResource>(IEnumerable<TResource> ent
5760
var diff = new DiffableEntityHashSet<TResource>(node.UniqueEntities, dbValues, node.LeftsToNextLayer(), _targetedFields);
5861
IEnumerable<TResource> updated = container.BeforeUpdate(diff, pipeline);
5962
node.UpdateUnique(updated);
60-
node.Reassign(entities);
63+
node.Reassign(_resourceFactory, entities);
6164
}
6265

6366
FireNestedBeforeUpdateHooks(pipeline, _traversalHelper.CreateNextLayer(node));
@@ -72,7 +75,7 @@ public IEnumerable<TResource> BeforeCreate<TResource>(IEnumerable<TResource> ent
7275
var affected = new EntityHashSet<TResource>((HashSet<TResource>)node.UniqueEntities, node.LeftsToNextLayer());
7376
IEnumerable<TResource> updated = container.BeforeCreate(affected, pipeline);
7477
node.UpdateUnique(updated);
75-
node.Reassign(entities);
78+
node.Reassign(_resourceFactory, entities);
7679
}
7780
FireNestedBeforeUpdateHooks(pipeline, _traversalHelper.CreateNextLayer(node));
7881
return entities;
@@ -89,7 +92,7 @@ public IEnumerable<TResource> BeforeDelete<TResource>(IEnumerable<TResource> ent
8992

9093
IEnumerable<TResource> updated = container.BeforeDelete(affected, pipeline);
9194
node.UpdateUnique(updated);
92-
node.Reassign(entities);
95+
node.Reassign(_resourceFactory, entities);
9396
}
9497

9598
// If we're deleting an article, we're implicitly affected any owners related to it.
@@ -113,14 +116,14 @@ public IEnumerable<TResource> OnReturn<TResource>(IEnumerable<TResource> entitie
113116
IEnumerable<TResource> updated = container.OnReturn((HashSet<TResource>)node.UniqueEntities, pipeline);
114117
ValidateHookResponse(updated);
115118
node.UpdateUnique(updated);
116-
node.Reassign(entities);
119+
node.Reassign(_resourceFactory, entities);
117120
}
118121

119122
Traverse(_traversalHelper.CreateNextLayer(node), ResourceHook.OnReturn, (nextContainer, nextNode) =>
120123
{
121124
var filteredUniqueSet = CallHook(nextContainer, ResourceHook.OnReturn, new object[] { nextNode.UniqueEntities, pipeline });
122125
nextNode.UpdateUnique(filteredUniqueSet);
123-
nextNode.Reassign();
126+
nextNode.Reassign(_resourceFactory);
124127
});
125128
return entities;
126129
}
@@ -270,7 +273,7 @@ private void FireNestedBeforeUpdateHooks(ResourcePipeline pipeline, NodeLayer la
270273
var allowedIds = CallHook(nestedHookContainer, ResourceHook.BeforeUpdateRelationship, new object[] { GetIds(uniqueEntities), resourcesByRelationship, pipeline }).Cast<string>();
271274
var updated = GetAllowedEntities(uniqueEntities, allowedIds);
272275
node.UpdateUnique(updated);
273-
node.Reassign();
276+
node.Reassign(_resourceFactory);
274277
}
275278
}
276279

src/JsonApiDotNetCore/Hooks/Traversal/ChildNode.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ public void UpdateUnique(IEnumerable updated)
5353
/// <summary>
5454
/// Reassignment is done according to provided relationships
5555
/// </summary>
56-
/// <param name="updated"></param>
57-
public void Reassign(IEnumerable updated = null)
56+
public void Reassign(IResourceFactory resourceFactory, IEnumerable updated = null)
5857
{
5958
var unique = (HashSet<TResource>)UniqueEntities;
6059
foreach (var group in _relationshipsFromPreviousLayer)
@@ -70,13 +69,13 @@ public void Reassign(IEnumerable updated = null)
7069
{
7170
var intersection = relationshipCollection.Intersect(unique, _comparer);
7271
IEnumerable typedCollection = intersection.CopyToTypedCollection(relationshipCollection.GetType());
73-
proxy.SetValue(left, typedCollection);
72+
proxy.SetValue(left, typedCollection, resourceFactory);
7473
}
7574
else if (currentValue is IIdentifiable relationshipSingle)
7675
{
7776
if (!unique.Intersect(new HashSet<IIdentifiable> { relationshipSingle }, _comparer).Any())
7877
{
79-
proxy.SetValue(left, null);
78+
proxy.SetValue(left, null, resourceFactory);
8079
}
8180
}
8281
}

src/JsonApiDotNetCore/Hooks/Traversal/IEntityNode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections;
2+
using JsonApiDotNetCore.Internal;
23
using RightType = System.Type;
34

45
namespace JsonApiDotNetCore.Hooks
@@ -30,7 +31,7 @@ internal interface INode
3031
/// A helper method to assign relationships to the previous layer after firing hooks.
3132
/// Or, in case of the root node, to update the original source enumerable.
3233
/// </summary>
33-
void Reassign(IEnumerable source = null);
34+
void Reassign(IResourceFactory resourceFactory, IEnumerable source = null);
3435
/// <summary>
3536
/// A helper method to internally update the unique set of entities as a result of
3637
/// a filter action in a hook.

src/JsonApiDotNetCore/Hooks/Traversal/RelationshipProxy.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using JsonApiDotNetCore.Extensions;
5+
using JsonApiDotNetCore.Internal;
56
using JsonApiDotNetCore.Models;
67

78
namespace JsonApiDotNetCore.Hooks
@@ -81,7 +82,8 @@ public object GetValue(IIdentifiable entity)
8182
/// </summary>
8283
/// <param name="entity">Parent entity.</param>
8384
/// <param name="value">The relationship value.</param>
84-
public void SetValue(IIdentifiable entity, object value)
85+
/// <param name="resourceFactory"></param>
86+
public void SetValue(IIdentifiable entity, object value, IResourceFactory resourceFactory)
8587
{
8688
if (Attribute is HasManyThroughAttribute hasManyThrough)
8789
{
@@ -108,7 +110,7 @@ public void SetValue(IIdentifiable entity, object value)
108110
return;
109111
}
110112

111-
Attribute.SetValue(entity, value);
113+
Attribute.SetValue(entity, value, resourceFactory);
112114
}
113115
}
114116
}

src/JsonApiDotNetCore/Hooks/Traversal/RootNode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void UpdateUnique(IEnumerable updated)
5959
_uniqueEntities = new HashSet<TResource>(intersected);
6060
}
6161

62-
public void Reassign(IEnumerable source = null)
62+
public void Reassign(IResourceFactory resourceFactory, IEnumerable source = null)
6363
{
6464
var ids = _uniqueEntities.Select(ue => ue.StringId);
6565

src/JsonApiDotNetCore/Internal/Generics/RepositoryRelationshipUpdateHelper.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ public interface IRepositoryRelationshipUpdateHelper
3333
/// <inheritdoc/>
3434
public class RepositoryRelationshipUpdateHelper<TRelatedResource> : IRepositoryRelationshipUpdateHelper where TRelatedResource : class
3535
{
36+
private readonly IResourceFactory _resourceFactory;
3637
private readonly DbContext _context;
37-
public RepositoryRelationshipUpdateHelper(IDbContextResolver contextResolver)
38+
39+
public RepositoryRelationshipUpdateHelper(IDbContextResolver contextResolver, IResourceFactory resourceFactory)
3840
{
41+
_resourceFactory = resourceFactory;
3942
_context = contextResolver.GetContext();
4043
}
4144

@@ -65,7 +68,7 @@ private async Task UpdateOneToOneAsync(IIdentifiable parent, RelationshipAttribu
6568
var equalsLambda = Expression.Lambda<Func<TRelatedResource, bool>>(callEquals, parameter);
6669
value = await _context.Set<TRelatedResource>().FirstOrDefaultAsync(equalsLambda);
6770
}
68-
relationship.SetValue(parent, value);
71+
relationship.SetValue(parent, value, _resourceFactory);
6972
}
7073

7174
private async Task UpdateOneToManyAsync(IIdentifiable parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
@@ -95,7 +98,7 @@ private async Task UpdateOneToManyAsync(IIdentifiable parent, RelationshipAttrib
9598
value = resultSet.CopyToTypedCollection(relationship.PropertyInfo.PropertyType);
9699
}
97100

98-
relationship.SetValue(parent, value);
101+
relationship.SetValue(parent, value, _resourceFactory);
99102
}
100103

101104
private async Task UpdateManyToManyAsync(IIdentifiable parent, HasManyThroughAttribute relationship, IEnumerable<string> relationshipIds)
@@ -125,7 +128,7 @@ private async Task UpdateManyToManyAsync(IIdentifiable parent, HasManyThroughAtt
125128

126129
var newLinks = relationshipIds.Select(x =>
127130
{
128-
var link = TypeHelper.CreateInstance(relationship.ThroughType);
131+
var link = _resourceFactory.CreateInstance(relationship.ThroughType);
129132
relationship.LeftIdProperty.SetValue(link, TypeHelper.ConvertType(parentId, relationship.LeftIdProperty.PropertyType));
130133
relationship.RightIdProperty.SetValue(link, TypeHelper.ConvertType(x, relationship.RightIdProperty.PropertyType));
131134
return link;

src/JsonApiDotNetCore/Internal/IResourceFactory.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ namespace JsonApiDotNetCore.Internal
1010
{
1111
public interface IResourceFactory
1212
{
13-
public IIdentifiable CreateInstance(Type resourceType);
14-
public TResource CreateInstance<TResource>() where TResource : IIdentifiable;
13+
public object CreateInstance(Type resourceType);
14+
public TResource CreateInstance<TResource>();
1515
public NewExpression CreateNewExpression(Type resourceType);
1616
}
1717

@@ -24,17 +24,17 @@ public DefaultResourceFactory(IServiceProvider serviceProvider)
2424
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
2525
}
2626

27-
public IIdentifiable CreateInstance(Type resourceType)
27+
public object CreateInstance(Type resourceType)
2828
{
2929
if (resourceType == null)
3030
{
3131
throw new ArgumentNullException(nameof(resourceType));
3232
}
3333

34-
return (IIdentifiable) InnerCreateInstance(resourceType, _serviceProvider);
34+
return InnerCreateInstance(resourceType, _serviceProvider);
3535
}
3636

37-
public TResource CreateInstance<TResource>() where TResource : IIdentifiable
37+
public TResource CreateInstance<TResource>()
3838
{
3939
return (TResource) InnerCreateInstance(typeof(TResource), _serviceProvider);
4040
}

src/JsonApiDotNetCore/Internal/TypeHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ public static object CreateInstance(Type type)
240240

241241
public static object ConvertStringIdToTypedId(Type resourceType, string stringId, IResourceFactory resourceFactory)
242242
{
243-
var tempResource = resourceFactory.CreateInstance(resourceType);
243+
var tempResource = (IIdentifiable)resourceFactory.CreateInstance(resourceType);
244244
tempResource.StringId = stringId;
245245
return GetResourceTypedId(tempResource);
246246
}

0 commit comments

Comments
 (0)