Skip to content

Commit eece47c

Browse files
committed
Finished removing GetPropertyMap, adds GetProperties to accomodate one of the use cases. Added tests.
1 parent 721f98a commit eece47c

File tree

4 files changed

+62
-25
lines changed

4 files changed

+62
-25
lines changed

JSONAPI.Tests/Core/ModelManagerTests.cs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,35 +42,60 @@ public void DoesntFindMissingId()
4242
}
4343

4444
[TestMethod]
45-
public void GetPropertyMapTest()
45+
public void GetJsonKeyForTypeTest()
4646
{
4747
// Arrange
48-
var mm = new ModelManager();
48+
var pluralizationService = new PluralizationService();
49+
var mm = new ModelManager(pluralizationService);
4950

5051
// Act
51-
var propMap = mm.GetPropertyMap(typeof(Post));
52-
52+
var postKey = mm.GetJsonKeyForType(typeof(Post));
53+
var authorKey = mm.GetJsonKeyForType(typeof(Author));
54+
var commentKey = mm.GetJsonKeyForType(typeof(Comment));
55+
5356
// Assert
54-
Assert.AreSame(typeof(Post).GetProperty("Id"), propMap["id"]);
55-
Assert.AreSame(typeof(Post).GetProperty("Author"), propMap["author"]);
57+
Assert.AreEqual("posts", postKey);
58+
Assert.AreEqual("authors", authorKey);
59+
Assert.AreEqual("comments", commentKey);
5660
}
5761

5862
[TestMethod]
59-
public void GetJsonKeyForTypeTest()
63+
public void GetJsonKeyForPropertyTest()
6064
{
6165
// Arrange
6266
var pluralizationService = new PluralizationService();
6367
var mm = new ModelManager(pluralizationService);
6468

6569
// Act
66-
var postKey = mm.GetJsonKeyForType(typeof(Post));
67-
var authorKey = mm.GetJsonKeyForType(typeof(Author));
68-
var commentKey = mm.GetJsonKeyForType(typeof(Comment));
70+
var idKey = mm.GetJsonKeyForProperty(typeof(Author).GetProperty("Id"));
71+
var nameKey = mm.GetJsonKeyForProperty(typeof(Author).GetProperty("Name"));
72+
var postsKey = mm.GetJsonKeyForProperty(typeof(Author).GetProperty("Posts"));
6973

7074
// Assert
71-
Assert.AreEqual("posts", postKey);
72-
Assert.AreEqual("authors", authorKey);
73-
Assert.AreEqual("comments", commentKey);
75+
Assert.AreEqual("id", idKey);
76+
Assert.AreEqual("name", nameKey);
77+
Assert.AreEqual("posts", postsKey);
78+
79+
}
80+
81+
[TestMethod]
82+
public void GetPropertyForJsonKeyTest()
83+
{
84+
// Arrange
85+
var pluralizationService = new PluralizationService();
86+
var mm = new ModelManager(pluralizationService);
87+
Type authorType = typeof(Author).GetType();
88+
89+
// Act
90+
var idProp = mm.GetPropertyForJsonKey(authorType, "id");
91+
var nameProp = mm.GetPropertyForJsonKey(authorType, "name");
92+
var postsProp = mm.GetPropertyForJsonKey(authorType, "posts");
93+
94+
// Assert
95+
Assert.AreSame(authorType.GetProperty("Id"), idProp);
96+
Assert.AreSame(authorType.GetProperty("Name"), nameProp);
97+
Assert.AreSame(authorType.GetProperty("Posts"), postsProp);
98+
7499
}
75100
}
76101
}

JSONAPI/Core/IModelManager.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,19 @@ public interface IModelManager
1313

1414
PropertyInfo GetIdProperty(Type type);
1515
string GetJsonKeyForType(Type type);
16-
string GetJsonKeyForProperty(PropertyInfo propInfo); //TODO: Do we need to have a type parameter here, in case propInfo is inherited?
16+
string GetJsonKeyForProperty(PropertyInfo propInfo); //TODO: Do we need to have a type parameter here, in case the property is inherited?
1717
PropertyInfo GetPropertyForJsonKey(Type type, string jsonKey);
1818

19-
[Obsolete]
20-
IDictionary<string, PropertyInfo> GetPropertyMap(Type type);
19+
/// <summary>
20+
/// Analogue to System.Type.GetProperties(), but made available so that any caching done
21+
/// by an IModelManager can be leveraged to return the results faster.
22+
/// </summary>
23+
/// <param name="type">The type to get properties from</param>
24+
/// <returns>All properties recognized by the IModelManager.</returns>
25+
//TODO: This needs to include JsonIgnore'd properties, so that they can be found and explicitly included at runtime...confusing? Add another method that excludes these?
26+
PropertyInfo[] GetProperties(Type type);
27+
28+
//[Obsolete]
29+
//IDictionary<string, PropertyInfo> GetPropertyMap(Type type);
2130
}
2231
}

JSONAPI/Core/ModelManager.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public PropertyInfo GetIdProperty(Type type)
7676

7777
#region Property Maps
7878

79-
public IDictionary<string, PropertyInfo> GetPropertyMap(Type type) //FIXME: Will become protected
79+
protected IDictionary<string, PropertyInfo> GetPropertyMap(Type type) //FIXME: Will become protected
8080
{
8181
Dictionary<string, PropertyInfo> propMap = null;
8282

@@ -99,6 +99,11 @@ public IDictionary<string, PropertyInfo> GetPropertyMap(Type type) //FIXME: Will
9999
return propMap;
100100
}
101101

102+
public PropertyInfo[] GetProperties(Type type)
103+
{
104+
return GetPropertyMap(type).Values.ToArray();
105+
}
106+
102107
public PropertyInfo GetPropertyForJsonKey(Type type, string jsonKey)
103108
{
104109
PropertyInfo propInfo;

JSONAPI/Json/JsonApiFormatter.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
175175
var idProp = _modelManager.GetIdProperty(value.GetType());
176176
writer.WriteValue(GetValueForIdProperty(idProp, value));
177177

178-
// Leverage the cached map to avoid another costly call to GetProperties()
179-
PropertyInfo[] props = _modelManager.GetPropertyMap(value.GetType()).Values.ToArray();
178+
// Leverage the cached map to avoid another costly call to System.Type.GetProperties()
179+
PropertyInfo[] props = _modelManager.GetProperties(value.GetType());
180180

181181
// Do non-model properties first, everything else goes in "links"
182182
//TODO: Unless embedded???
@@ -573,8 +573,6 @@ public object Deserialize(Type objectType, Stream readStream, JsonReader reader,
573573
{
574574
object retval = Activator.CreateInstance(objectType);
575575

576-
IDictionary<string, PropertyInfo> propMap = _modelManager.GetPropertyMap(objectType);
577-
578576
if (reader.TokenType != JsonToken.StartObject) throw new JsonReaderException(String.Format("Expected JsonToken.StartObject, got {0}", reader.TokenType.ToString()));
579577
reader.Read(); // Burn the StartObject token
580578
do
@@ -589,7 +587,7 @@ public object Deserialize(Type objectType, Stream readStream, JsonReader reader,
589587
//TODO: linked resources (Done??)
590588
DeserializeLinkedResources(retval, readStream, reader, serializer);
591589
}
592-
else if (propMap.TryGetValue(value, out prop))
590+
else if ((prop = _modelManager.GetPropertyForJsonKey(objectType, value)) != null)
593591
{
594592
reader.Read(); // burn the PropertyName token
595593
//TODO: Embedded would be dropped here!
@@ -657,16 +655,16 @@ private void DeserializeLinkedResources(object obj, Stream readStream, JsonReade
657655
//reader.Read();
658656
if (reader.TokenType != JsonToken.StartObject) throw new JsonSerializationException("'links' property is not an object!");
659657

660-
IDictionary<string, PropertyInfo> propMap = _modelManager.GetPropertyMap(obj.GetType());
658+
Type objectType = obj.GetType();
661659

662660
while (reader.Read())
663661
{
664662
if (reader.TokenType == JsonToken.PropertyName)
665663
{
666664
string value = (string)reader.Value;
667665
reader.Read(); // burn the PropertyName token
668-
PropertyInfo prop;
669-
if (propMap.TryGetValue(value, out prop) && !CanWriteTypeAsPrimitive(prop.PropertyType))
666+
PropertyInfo prop = _modelManager.GetPropertyForJsonKey(objectType, value);
667+
if (prop != null && !CanWriteTypeAsPrimitive(prop.PropertyType))
670668
{
671669
//FIXME: We're really assuming they're ICollections...but testing for that doesn't work for some reason. Break prone!
672670
if (prop.PropertyType.GetInterfaces().Contains(typeof(IEnumerable)) && prop.PropertyType.IsGenericType)

0 commit comments

Comments
 (0)