From 1703992773b08532d2adad1bf073c849b35a8f88 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Sat, 16 Oct 2010 10:45:36 +0000 Subject: [PATCH] -Added covariance to IJEnumerable type parameter -Fixed inaccessible private getter/setters on base classes --- .../Linq/LinqToJsonTest.cs | 15 ++++++ .../Serialization/JsonSerializerTest.cs | 49 +++++++++++++++++++ Src/Newtonsoft.Json/Linq/IJEnumerable.cs | 6 ++- .../Utilities/ReflectionUtils.cs | 17 +++++-- 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs b/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs index 749d8b30..fcaf7f00 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/LinqToJsonTest.cs @@ -698,6 +698,21 @@ keyword such as type of business."" Assert.AreEqual(new DateTime(2000, 10, 15, 5, 5, 5, DateTimeKind.Utc), d); } +#if !(NET20 || NET35 || SILVERLIGHT) + [Test] + public void CovariantIJEnumerable() + { + IEnumerable o = new[] + { + JObject.FromObject(new {First = 1, Second = 2}), + JObject.FromObject(new {First = 1, Second = 2}) + }; + + IJEnumerable values = o.Properties(); + Assert.AreEqual(4, values.Count()); + } +#endif + [Test] public void ChildrenExtension() { diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 74d89f5d..8178da58 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -3697,5 +3697,54 @@ keyword such as type of business."" Assert.AreEqual(2, obj.Position.Y); Assert.AreEqual(3, obj.Position.Z); } + + [JsonObject(MemberSerialization.OptIn)] + public class Derived : Base + { + [JsonProperty] + public string IDoWork { get; private set; } + + private Derived() { } + + internal Derived(string dontWork, string doWork) + : base(dontWork) + { + IDoWork = doWork; + } + } + + [JsonObject(MemberSerialization.OptIn)] + public class Base + { + [JsonProperty] + public string IDontWork { get; private set; } + + protected Base() { } + + internal Base(string dontWork) + { + IDontWork = dontWork; + } + } + + [Test] + public void PrivateSetterOnBaseClassProperty() + { + var derived = new Derived("meh", "woo"); + + var settings = new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects, + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor + }; + + string json = JsonConvert.SerializeObject(derived, Formatting.Indented, settings); + + var meh = JsonConvert.DeserializeObject(json, settings); + + Assert.AreEqual(((Derived)meh).IDoWork, "woo"); + Assert.AreEqual(meh.IDontWork, "meh"); + } + } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/IJEnumerable.cs b/Src/Newtonsoft.Json/Linq/IJEnumerable.cs index a758fcb1..6291e99f 100644 --- a/Src/Newtonsoft.Json/Linq/IJEnumerable.cs +++ b/Src/Newtonsoft.Json/Linq/IJEnumerable.cs @@ -9,7 +9,11 @@ namespace Newtonsoft.Json.Linq /// Represents a collection of objects. /// /// The type of token - public interface IJEnumerable : IEnumerable where T : JToken + public interface IJEnumerable< +#if !(NET20 || NET35 || SILVERLIGHT) + out +#endif + T> : IEnumerable where T : JToken { /// /// Gets the with the specified key. diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index 7419ba83..e2bb83b1 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -880,10 +880,21 @@ namespace Newtonsoft.Json.Utilities { ValidationUtils.ArgumentNotNull(targetType, "targetType"); - List propertyInfos = new List(targetType.GetProperties(bindingAttr)); + List propertyInfos = new List(targetType.GetProperties(bindingAttr)); GetChildPrivateProperties(propertyInfos, targetType, bindingAttr); - return propertyInfos.Cast(); + // a base class private getter/setter will be inaccessable unless the property was gotten from the base class + for (int i = 0; i < propertyInfos.Count; i++) + { + PropertyInfo member = propertyInfos[i]; + if (member.DeclaringType != targetType) + { + PropertyInfo declaredMember = member.DeclaringType.GetProperty(member.Name, bindingAttr); + propertyInfos[i] = declaredMember; + } + } + + return propertyInfos; } public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag) @@ -893,7 +904,7 @@ namespace Newtonsoft.Json.Utilities : bindingAttr; } - private static void GetChildPrivateProperties(IList initialProperties, Type targetType, BindingFlags bindingAttr) + private static void GetChildPrivateProperties(IList initialProperties, Type targetType, BindingFlags bindingAttr) { // fix weirdness with private PropertyInfos only being returned for the current Type // find base type properties and add them to result