Skip to content

Commit b01fa0a

Browse files
committed
Merge pull request #24 from SphtKr/move-getidproperty
Closes #22 and begins to address #23.
2 parents ab9ed6a + ffc3413 commit b01fa0a

File tree

6 files changed

+125
-5
lines changed

6 files changed

+125
-5
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using JSONAPI.Core;
4+
using JSONAPI.Tests.Models;
5+
using System.Reflection;
6+
7+
namespace JSONAPI.Tests.Core
8+
{
9+
[TestClass]
10+
public class ModelManagerTests
11+
{
12+
private class InvalidModel
13+
{
14+
public string Data { get; set; }
15+
}
16+
17+
[TestMethod]
18+
public void FindsIdNamedId()
19+
{
20+
// Arrange
21+
var mm = new ModelManager();
22+
23+
// Act
24+
PropertyInfo idprop = mm.GetIdProperty(typeof(Author));
25+
26+
// Assert
27+
Assert.AreSame(typeof(Author).GetProperty("Id"), idprop);
28+
}
29+
30+
[TestMethod]
31+
[ExpectedException(typeof(InvalidOperationException))]
32+
public void DoesntFindMissingId()
33+
{
34+
// Arrange
35+
var mm = new ModelManager();
36+
37+
// Act
38+
PropertyInfo idprop = mm.GetIdProperty(typeof(InvalidModel));
39+
40+
// Assert
41+
Assert.Fail("An InvalidOperationException should be thrown and we shouldn't get here!");
42+
}
43+
}
44+
}

JSONAPI.Tests/JSONAPI.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
<ItemGroup>
7878
<Compile Include="ActionFilters\EnableFilteringAttributeTests.cs" />
7979
<Compile Include="Core\MetadataManagerTests.cs" />
80+
<Compile Include="Core\ModelManagerTests.cs" />
8081
<Compile Include="Json\ErrorSerializerTests.cs" />
8182
<Compile Include="Json\JsonApiMediaFormaterTests.cs" />
8283
<Compile Include="Json\JsonHelpers.cs" />

JSONAPI/Core/IModelManager.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace JSONAPI.Core
9+
{
10+
public interface IModelManager
11+
{
12+
PropertyInfo GetIdProperty(Type type);
13+
}
14+
}

JSONAPI/Core/ModelManager.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace JSONAPI.Core
9+
{
10+
public class ModelManager : IModelManager
11+
{
12+
public ModelManager() { }
13+
14+
#region Cache storage
15+
16+
private Lazy<Dictionary<Type, PropertyInfo>> _idProperties
17+
= new Lazy<Dictionary<Type,PropertyInfo>>(
18+
() => new Dictionary<Type, PropertyInfo>()
19+
);
20+
21+
#endregion
22+
23+
#region Id property determination
24+
25+
public PropertyInfo GetIdProperty(Type type)
26+
{
27+
PropertyInfo idprop = null;
28+
29+
var idPropCache = _idProperties.Value;
30+
31+
lock (idPropCache)
32+
{
33+
if (idPropCache.TryGetValue(type, out idprop)) return idprop;
34+
35+
//TODO: Enable attribute-based determination
36+
37+
idprop = type.GetProperty("Id");
38+
39+
if (idprop == null)
40+
throw new InvalidOperationException(String.Format("Unable to determine Id property for type {0}", type));
41+
42+
idPropCache.Add(type, idprop);
43+
}
44+
45+
return idprop;
46+
}
47+
48+
#endregion
49+
}
50+
}

JSONAPI/JSONAPI.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@
6868
<Compile Include="Attributes\IncludeInPayload.cs" />
6969
<Compile Include="Attributes\LinkTemplate.cs" />
7070
<Compile Include="Attributes\SerializeAs.cs" />
71+
<Compile Include="Core\IModelManager.cs" />
7172
<Compile Include="Core\IPluralizationService.cs" />
7273
<Compile Include="Core\IMaterializer.cs" />
7374
<Compile Include="Core\MetadataManager.cs" />
75+
<Compile Include="Core\ModelManager.cs" />
7476
<Compile Include="Http\ApiController.cs" />
7577
<Compile Include="Json\ErrorSerializer.cs" />
7678
<Compile Include="Json\GuidErrorIdProvider.cs" />

JSONAPI/Json/JsonApiFormatter.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,23 @@ public class JsonApiFormatter : JsonMediaTypeFormatter
2222
public JsonApiFormatter()
2323
: this(new ErrorSerializer())
2424
{
25+
if (_modelManager == null) _modelManager = new ModelManager();
26+
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.api+json"));
2527
}
2628

2729
internal JsonApiFormatter(IErrorSerializer errorSerializer)
2830
{
2931
_errorSerializer = errorSerializer;
30-
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.api+json"));
3132
}
3233

33-
public IPluralizationService PluralizationService { get; set; }
34+
public JsonApiFormatter(IModelManager modelManager) : this()
35+
{
36+
_modelManager = modelManager;
37+
}
38+
39+
public IPluralizationService PluralizationService { get; set; } //FIXME: Deprecated, will be removed shortly
3440
private readonly IErrorSerializer _errorSerializer;
41+
private readonly IModelManager _modelManager;
3542

3643
private Lazy<Dictionary<Stream, RelationAggregator>> _relationAggregators
3744
= new Lazy<Dictionary<Stream, RelationAggregator>>(
@@ -152,7 +159,7 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
152159

153160
// Do the Id now...
154161
writer.WritePropertyName("id");
155-
var idProp = GetIdProperty(value.GetType());
162+
var idProp = _modelManager.GetIdProperty(value.GetType());
156163
writer.WriteValue(GetValueForIdProperty(idProp, value));
157164

158165
PropertyInfo[] props = value.GetType().GetProperties();
@@ -819,15 +826,17 @@ protected object GetById(Type type, string id)
819826
{
820827
// Only good for creating dummy relationship objects...
821828
object retval = Activator.CreateInstance(type);
822-
PropertyInfo idprop = GetIdProperty(type);
829+
PropertyInfo idprop = _modelManager.GetIdProperty(type);
823830
idprop.SetValue(retval, System.Convert.ChangeType(id, idprop.PropertyType));
824831
return retval;
825832
}
826833

834+
/*
827835
protected PropertyInfo GetIdProperty(Type type)
828836
{
829837
return type.GetProperty("Id");
830838
}
839+
*/
831840

832841
protected string GetValueForIdProperty(PropertyInfo idprop, object obj)
833842
{
@@ -846,7 +855,7 @@ protected string GetValueForIdProperty(PropertyInfo idprop, object obj)
846855
protected string GetIdFor(object obj)
847856
{
848857
Type type = obj.GetType();
849-
PropertyInfo idprop = GetIdProperty(type);
858+
PropertyInfo idprop = _modelManager.GetIdProperty(type);
850859
return GetValueForIdProperty(idprop, obj);
851860
}
852861

0 commit comments

Comments
 (0)