Skip to content

Commit dd12e38

Browse files
committed
fix(Deserializer): remove dependency on GenericProcessorFactory
Rather than fetching data from the database during deserialization, we can set the relationships with instances that just carry the id. It will then be the responsibility of the repository to handle those relationships
1 parent 906c697 commit dd12e38

File tree

3 files changed

+88
-8
lines changed

3 files changed

+88
-8
lines changed

src/JsonApiDotNetCore/Extensions/TypeExtensions.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,28 @@ public static Type GetElementType(this IEnumerable enumerable)
3131

3232
return elementType;
3333
}
34+
35+
/// <summary>
36+
/// Creates a List{TInterface} where TInterface is the generic for type specified by t
37+
/// </summary>
38+
public static List<TInterface> GetEmptyCollection<TInterface>(this Type t)
39+
{
40+
if (t == null) throw new ArgumentNullException(nameof(t));
41+
42+
var listType = typeof(List<>).MakeGenericType(t);
43+
var list = (List<TInterface>)Activator.CreateInstance(listType);
44+
return list;
45+
}
46+
47+
/// <summary>
48+
/// Creates a new instance of type t, casting it to the specified TInterface
49+
/// </summary>
50+
public static TInterface New<TInterface>(this Type t)
51+
{
52+
if (t == null) throw new ArgumentNullException(nameof(t));
53+
54+
var instance = (TInterface)Activator.CreateInstance(t);
55+
return instance;
56+
}
3457
}
3558
}

src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,27 @@
99
using JsonApiDotNetCore.Services;
1010
using Newtonsoft.Json;
1111
using Newtonsoft.Json.Linq;
12+
using JsonApiDotNetCore.Extensions;
1213

1314
namespace JsonApiDotNetCore.Serialization
1415
{
1516
public class JsonApiDeSerializer : IJsonApiDeSerializer
1617
{
1718
private readonly IJsonApiContext _jsonApiContext;
18-
private readonly IGenericProcessorFactory _genericProcessorFactory;
1919

20+
[Obsolete(
21+
"The deserializer no longer depends on the IGenericProcessorFactory",
22+
error: false)]
2023
public JsonApiDeSerializer(
2124
IJsonApiContext jsonApiContext,
2225
IGenericProcessorFactory genericProcessorFactory)
2326
{
2427
_jsonApiContext = jsonApiContext;
25-
_genericProcessorFactory = genericProcessorFactory;
28+
}
29+
30+
public JsonApiDeSerializer(IJsonApiContext jsonApiContext)
31+
{
32+
_jsonApiContext = jsonApiContext;
2633
}
2734

2835
public object Deserialize(string requestBody)
@@ -225,10 +232,11 @@ private object SetHasManyRelationship(object entity,
225232
ContextEntity contextEntity,
226233
Dictionary<string, RelationshipData> relationships)
227234
{
228-
var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
235+
// TODO: is this necessary? if not, remove
236+
// var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
229237

230-
if (entityProperty == null)
231-
throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain an relationsip named {attr.InternalRelationshipName}");
238+
// if (entityProperty == null)
239+
// throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a relationsip named '{attr.InternalRelationshipName}'");
232240

233241
var relationshipName = attr.PublicRelationshipName;
234242

@@ -238,11 +246,16 @@ private object SetHasManyRelationship(object entity,
238246

239247
if (data == null) return entity;
240248

241-
var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), attr.Type);
249+
var resourceRelationships = attr.Type.GetEmptyCollection<IIdentifiable>();
242250

243-
var ids = relationshipData.ManyData.Select(r => r.Id);
251+
var relationshipShells = relationshipData.ManyData.Select(r =>
252+
{
253+
var instance = attr.Type.New<IIdentifiable>();
254+
instance.StringId = r.Id;
255+
return instance;
256+
});
244257

245-
genericProcessor.SetRelationships(entity, attr, ids);
258+
attr.SetValue(entity, relationshipShells);
246259
}
247260

248261
return entity;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using JsonApiDotNetCore.Models;
2+
using Xunit;
3+
using JsonApiDotNetCore.Extensions;
4+
using System.Collections.Generic;
5+
6+
namespace UnitTests.Extensions
7+
{
8+
public class TypeExtensions_Tests
9+
{
10+
[Fact]
11+
public void GetCollection_Creates_List_If_T_Implements_Interface()
12+
{
13+
// arrange
14+
var type = typeof(Model);
15+
16+
// act
17+
var collection = type.GetEmptyCollection<IIdentifiable>();
18+
19+
// assert
20+
Assert.NotNull(collection);
21+
Assert.Empty(collection);
22+
Assert.IsType<List<Model>>(collection);
23+
}
24+
25+
[Fact]
26+
public void New_Creates_An_Instance_If_T_Implements_Interface()
27+
{
28+
// arrange
29+
var type = typeof(Model);
30+
31+
// act
32+
var instance = type.New<IIdentifiable>();
33+
34+
// assert
35+
Assert.NotNull(instance);
36+
Assert.IsType<Model>(instance);
37+
}
38+
39+
private class Model : IIdentifiable
40+
{
41+
public string StringId { get; set; }
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)