Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions JSONAPI.Tests/Core/ModelManagerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using JSONAPI.Core;
using JSONAPI.Tests.Models;
using System.Reflection;

namespace JSONAPI.Tests.Core
{
[TestClass]
public class ModelManagerTests
{
private class InvalidModel
{
public string Data { get; set; }
}

[TestMethod]
public void FindsIdNamedId()
{
// Arrange
var mm = new ModelManager();

// Act
PropertyInfo idprop = mm.GetIdProperty(typeof(Author));

// Assert
Assert.AreSame(typeof(Author).GetProperty("Id"), idprop);
}

[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void DoesntFindMissingId()
{
// Arrange
var mm = new ModelManager();

// Act
PropertyInfo idprop = mm.GetIdProperty(typeof(InvalidModel));

// Assert
Assert.Fail("An InvalidOperationException should be thrown and we shouldn't get here!");
}
}
}
1 change: 1 addition & 0 deletions JSONAPI.Tests/JSONAPI.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
<ItemGroup>
<Compile Include="ActionFilters\EnableFilteringAttributeTests.cs" />
<Compile Include="Core\MetadataManagerTests.cs" />
<Compile Include="Core\ModelManagerTests.cs" />
<Compile Include="Json\ErrorSerializerTests.cs" />
<Compile Include="Json\JsonApiMediaFormaterTests.cs" />
<Compile Include="Json\JsonHelpers.cs" />
Expand Down
14 changes: 14 additions & 0 deletions JSONAPI/Core/IModelManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace JSONAPI.Core
{
public interface IModelManager
{
PropertyInfo GetIdProperty(Type type);
}
}
50 changes: 50 additions & 0 deletions JSONAPI/Core/ModelManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace JSONAPI.Core
{
public class ModelManager : IModelManager
{
public ModelManager() { }

#region Cache storage

private Lazy<Dictionary<Type, PropertyInfo>> _idProperties
= new Lazy<Dictionary<Type,PropertyInfo>>(
() => new Dictionary<Type, PropertyInfo>()
);

#endregion

#region Id property determination

public PropertyInfo GetIdProperty(Type type)
{
PropertyInfo idprop = null;

var idPropCache = _idProperties.Value;

lock (idPropCache)
{
if (idPropCache.TryGetValue(type, out idprop)) return idprop;

//TODO: Enable attribute-based determination

idprop = type.GetProperty("Id");

if (idprop == null)
throw new InvalidOperationException(String.Format("Unable to determine Id property for type {0}", type));

idPropCache.Add(type, idprop);
}

return idprop;
}

#endregion
}
}
2 changes: 2 additions & 0 deletions JSONAPI/JSONAPI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@
<Compile Include="Attributes\IncludeInPayload.cs" />
<Compile Include="Attributes\LinkTemplate.cs" />
<Compile Include="Attributes\SerializeAs.cs" />
<Compile Include="Core\IModelManager.cs" />
<Compile Include="Core\IPluralizationService.cs" />
<Compile Include="Core\IMaterializer.cs" />
<Compile Include="Core\MetadataManager.cs" />
<Compile Include="Core\ModelManager.cs" />
<Compile Include="Http\ApiController.cs" />
<Compile Include="Json\ErrorSerializer.cs" />
<Compile Include="Json\GuidErrorIdProvider.cs" />
Expand Down
19 changes: 14 additions & 5 deletions JSONAPI/Json/JsonApiFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,23 @@ public class JsonApiFormatter : JsonMediaTypeFormatter
public JsonApiFormatter()
: this(new ErrorSerializer())
{
if (_modelManager == null) _modelManager = new ModelManager();
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.api+json"));
}

internal JsonApiFormatter(IErrorSerializer errorSerializer)
{
_errorSerializer = errorSerializer;
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.api+json"));
}

public IPluralizationService PluralizationService { get; set; }
public JsonApiFormatter(IModelManager modelManager) : this()
{
_modelManager = modelManager;
}

public IPluralizationService PluralizationService { get; set; } //FIXME: Deprecated, will be removed shortly
private readonly IErrorSerializer _errorSerializer;
private readonly IModelManager _modelManager;

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

// Do the Id now...
writer.WritePropertyName("id");
var idProp = GetIdProperty(value.GetType());
var idProp = _modelManager.GetIdProperty(value.GetType());
writer.WriteValue(GetValueForIdProperty(idProp, value));

PropertyInfo[] props = value.GetType().GetProperties();
Expand Down Expand Up @@ -819,15 +826,17 @@ protected object GetById(Type type, string id)
{
// Only good for creating dummy relationship objects...
object retval = Activator.CreateInstance(type);
PropertyInfo idprop = GetIdProperty(type);
PropertyInfo idprop = _modelManager.GetIdProperty(type);
idprop.SetValue(retval, System.Convert.ChangeType(id, idprop.PropertyType));
return retval;
}

/*
protected PropertyInfo GetIdProperty(Type type)
{
return type.GetProperty("Id");
}
*/

protected string GetValueForIdProperty(PropertyInfo idprop, object obj)
{
Expand All @@ -846,7 +855,7 @@ protected string GetValueForIdProperty(PropertyInfo idprop, object obj)
protected string GetIdFor(object obj)
{
Type type = obj.GetType();
PropertyInfo idprop = GetIdProperty(type);
PropertyInfo idprop = _modelManager.GetIdProperty(type);
return GetValueForIdProperty(idprop, obj);
}

Expand Down