-Added covariance to IJEnumerable type parameter

-Fixed inaccessible private getter/setters on base classes
This commit is contained in:
JamesNK
2010-10-16 10:45:36 +00:00
parent 336f14b3d2
commit 1703992773
4 changed files with 83 additions and 4 deletions
@@ -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<JObject> o = new[]
{
JObject.FromObject(new {First = 1, Second = 2}),
JObject.FromObject(new {First = 1, Second = 2})
};
IJEnumerable<JToken> values = o.Properties();
Assert.AreEqual(4, values.Count());
}
#endif
[Test]
public void ChildrenExtension()
{
@@ -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<Base>(json, settings);
Assert.AreEqual(((Derived)meh).IDoWork, "woo");
Assert.AreEqual(meh.IDontWork, "meh");
}
}
}
+5 -1
View File
@@ -9,7 +9,11 @@ namespace Newtonsoft.Json.Linq
/// Represents a collection of <see cref="JToken"/> objects.
/// </summary>
/// <typeparam name="T">The type of token</typeparam>
public interface IJEnumerable<T> : IEnumerable<T> where T : JToken
public interface IJEnumerable<
#if !(NET20 || NET35 || SILVERLIGHT)
out
#endif
T> : IEnumerable<T> where T : JToken
{
/// <summary>
/// Gets the <see cref="IJEnumerable{JToken}"/> with the specified key.
@@ -880,10 +880,21 @@ namespace Newtonsoft.Json.Utilities
{
ValidationUtils.ArgumentNotNull(targetType, "targetType");
List<MemberInfo> propertyInfos = new List<MemberInfo>(targetType.GetProperties(bindingAttr));
List<PropertyInfo> propertyInfos = new List<PropertyInfo>(targetType.GetProperties(bindingAttr));
GetChildPrivateProperties(propertyInfos, targetType, bindingAttr);
return propertyInfos.Cast<PropertyInfo>();
// 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<MemberInfo> initialProperties, Type targetType, BindingFlags bindingAttr)
private static void GetChildPrivateProperties(IList<PropertyInfo> 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