-Fixed JsonProperty.Readable and Writable not being correctly set for .NET properties with modified getter/setter visibility
-Fixed error caused by property properties on a base class when reflecting a type -Fixed property CanRead and CanWrite coming back as false when a base class property has a private getter/setter visibility
This commit is contained in:
@@ -24,7 +24,9 @@ namespace Newtonsoft.Json.Tests
|
||||
[DataMember]
|
||||
public string FileName { get; set; }
|
||||
[DataMember]
|
||||
public string Title { get; set; }
|
||||
public string Author { get; set; }
|
||||
[DataMember]
|
||||
public string Caption { get; set; }
|
||||
[DataMember]
|
||||
public byte[] Data { get; set; }
|
||||
}
|
||||
@@ -94,44 +96,97 @@ namespace Newtonsoft.Json.Tests
|
||||
Image image = new Image();
|
||||
image.Data = System.IO.File.ReadAllBytes(@"..\..\bunny_pancake.jpg");
|
||||
image.FileName = "bunny_pancake.jpg";
|
||||
image.Title = "I have no idea what you are talking about so here's a bunny with a pancake on its head";
|
||||
image.Author = "Hironori Akutagawa";
|
||||
image.Caption = "I have no idea what you are talking about so here's a bunny with a pancake on its head";
|
||||
|
||||
SerializeSize(image);
|
||||
}
|
||||
|
||||
private T TimeOperation<T>(Func<T> operation, string name)
|
||||
{
|
||||
// warm up
|
||||
operation();
|
||||
|
||||
Stopwatch timed = new Stopwatch();
|
||||
timed.Start();
|
||||
|
||||
T result = operation();
|
||||
|
||||
Console.WriteLine(name);
|
||||
Console.WriteLine("{0} ms", timed.ElapsedMilliseconds);
|
||||
|
||||
timed.Stop();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SerializeSize(object value)
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(value, Formatting.None);
|
||||
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
|
||||
byte[] jsonBytes = TimeOperation(() =>
|
||||
{
|
||||
string json = null;
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
json = JsonConvert.SerializeObject(value, Formatting.None);
|
||||
}
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
BsonWriter writer = new BsonWriter(ms);
|
||||
return Encoding.UTF8.GetBytes(json);
|
||||
}, "Json.NET");
|
||||
|
||||
serializer.Serialize(writer, value);
|
||||
writer.Flush();
|
||||
byte[] bsonBytes = TimeOperation(() =>
|
||||
{
|
||||
MemoryStream ms = null;
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
ms = new MemoryStream();
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
BsonWriter writer = new BsonWriter(ms);
|
||||
|
||||
byte[] bsonBytes = ms.ToArray();
|
||||
serializer.Serialize(writer, value);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
DataContractSerializer dataContractSerializer = new DataContractSerializer(value.GetType());
|
||||
return ms.ToArray();
|
||||
}, "Json.NET BSON");
|
||||
|
||||
ms = new MemoryStream();
|
||||
dataContractSerializer.WriteObject(ms, value);
|
||||
byte[] xmlBytes = TimeOperation(() =>
|
||||
{
|
||||
MemoryStream ms = null;
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
ms = new MemoryStream();
|
||||
DataContractSerializer dataContractSerializer = new DataContractSerializer(value.GetType());
|
||||
dataContractSerializer.WriteObject(ms, value);
|
||||
}
|
||||
|
||||
byte[] xmlBytes = ms.ToArray();
|
||||
return ms.ToArray();
|
||||
}, "DataContractSerializer");
|
||||
|
||||
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(value.GetType());
|
||||
byte[] wcfJsonBytes = TimeOperation(() =>
|
||||
{
|
||||
MemoryStream ms = null;
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
ms = new MemoryStream();
|
||||
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(value.GetType());
|
||||
dataContractJsonSerializer.WriteObject(ms, value);
|
||||
}
|
||||
|
||||
ms = new MemoryStream();
|
||||
dataContractJsonSerializer.WriteObject(ms, value);
|
||||
return ms.ToArray();
|
||||
}, "DataContractJsonSerializer");
|
||||
|
||||
byte[] wcfJsonBytes = ms.ToArray();
|
||||
byte[] binaryFormatterBytes = TimeOperation(() =>
|
||||
{
|
||||
MemoryStream ms = null;
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
ms = new MemoryStream();
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
formatter.Serialize(ms, value);
|
||||
}
|
||||
|
||||
ms = new MemoryStream();
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
formatter.Serialize(ms, value);
|
||||
|
||||
byte[] binaryFormatterBytes = ms.ToArray();
|
||||
return ms.ToArray();
|
||||
}, "BinaryFormatter");
|
||||
|
||||
Console.WriteLine("Json.NET size: {0} bytes", jsonBytes.Length);
|
||||
Console.WriteLine("BSON size: {0} bytes", bsonBytes.Length);
|
||||
|
||||
@@ -47,6 +47,7 @@ using Newtonsoft.Json.Tests.TestObjects;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Serialization
|
||||
{
|
||||
@@ -417,7 +418,7 @@ keyword such as type of business.""
|
||||
public void BackslashEqivilence()
|
||||
{
|
||||
string json = @"[""vvv\/vvv\tvvv\""vvv\bvvv\nvvv\rvvv\\vvv\fvvv""]";
|
||||
|
||||
|
||||
#if !SILVERLIGHT
|
||||
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
|
||||
List<string> javaScriptSerializerResult = javaScriptSerializer.Deserialize<List<string>>(json);
|
||||
@@ -431,7 +432,7 @@ keyword such as type of business.""
|
||||
Assert.AreEqual(1, jsonNetResult.Count);
|
||||
Assert.AreEqual(dataContractResult[0], jsonNetResult[0]);
|
||||
#if !SILVERLIGHT
|
||||
Assert.AreEqual(javaScriptSerializerResult[0], jsonNetResult[0]);
|
||||
Assert.AreEqual(javaScriptSerializerResult[0], jsonNetResult[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2004,7 +2005,7 @@ keyword such as type of business.""
|
||||
""Newtonsoft.Json.Tests.TestObjects.Person"": 1,
|
||||
""Newtonsoft.Json.Tests.TestObjects.Person"": 2
|
||||
}";
|
||||
|
||||
|
||||
JsonConvert.DeserializeObject<Dictionary<Person, int>>(json);
|
||||
}
|
||||
|
||||
@@ -2093,7 +2094,7 @@ keyword such as type of business.""
|
||||
public void DeserializeBaseReferenceWithDerivedValue()
|
||||
{
|
||||
PersonPropertyClass personPropertyClass = new PersonPropertyClass();
|
||||
WagePerson wagePerson = (WagePerson) personPropertyClass.Person;
|
||||
WagePerson wagePerson = (WagePerson)personPropertyClass.Person;
|
||||
|
||||
wagePerson.BirthDate = new DateTime(2000, 11, 29, 23, 59, 59, DateTimeKind.Utc);
|
||||
wagePerson.Department = "McDees";
|
||||
@@ -2114,7 +2115,7 @@ keyword such as type of business.""
|
||||
json);
|
||||
|
||||
PersonPropertyClass newPersonPropertyClass = JsonConvert.DeserializeObject<PersonPropertyClass>(json);
|
||||
Assert.AreEqual(wagePerson.HourlyWage, ((WagePerson) newPersonPropertyClass.Person).HourlyWage);
|
||||
Assert.AreEqual(wagePerson.HourlyWage, ((WagePerson)newPersonPropertyClass.Person).HourlyWage);
|
||||
}
|
||||
|
||||
public class ExistingValueClass
|
||||
@@ -2328,13 +2329,13 @@ keyword such as type of business.""
|
||||
{
|
||||
var json = "{ Key: 'abc', Value: 123 }";
|
||||
var item = JsonConvert.DeserializeObject<TestClass>(json);
|
||||
|
||||
|
||||
Assert.AreEqual(123, item.Value);
|
||||
}
|
||||
|
||||
public abstract class Animal
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
public abstract string Name { get; }
|
||||
}
|
||||
|
||||
public class Human : Animal
|
||||
@@ -2364,7 +2365,7 @@ keyword such as type of business.""
|
||||
DataContractJsonSerializerTestClass c = new DataContractJsonSerializerTestClass();
|
||||
c.TimeSpanProperty = new TimeSpan(200, 20, 59, 30, 900);
|
||||
c.GuidProperty = new Guid("66143115-BE2A-4a59-AF0A-348E1EA15B1E");
|
||||
c.AnimalProperty = new Human() {Ethnicity = "European"};
|
||||
c.AnimalProperty = new Human() { Ethnicity = "European" };
|
||||
c.ExceptionProperty = ex;
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
@@ -2381,7 +2382,7 @@ keyword such as type of business.""
|
||||
|
||||
Console.WriteLine(JsonConvert.SerializeObject(c, Formatting.Indented, new JsonSerializerSettings
|
||||
{
|
||||
// TypeNameHandling = TypeNameHandling.Objects
|
||||
// TypeNameHandling = TypeNameHandling.Objects
|
||||
}));
|
||||
}
|
||||
#endif
|
||||
@@ -2670,5 +2671,181 @@ keyword such as type of business.""
|
||||
Assert.AreEqual(null, o2._nullableInt);
|
||||
}
|
||||
#endif
|
||||
|
||||
public class KVPair<TKey, TValue>
|
||||
{
|
||||
public TKey Key { get; set; }
|
||||
public TValue Value { get; set; }
|
||||
|
||||
public KVPair(TKey k, TValue v)
|
||||
{
|
||||
Key = k;
|
||||
Value = v;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeUsingNonDefaultConstructorWithLeftOverValues()
|
||||
{
|
||||
List<KVPair<string, string>> kvPairs =
|
||||
JsonConvert.DeserializeObject<List<KVPair<string, string>>>(
|
||||
"[{\"Key\":\"Two\",\"Value\":\"2\"},{\"Key\":\"One\",\"Value\":\"1\"}]");
|
||||
|
||||
Assert.AreEqual(2, kvPairs.Count);
|
||||
Assert.AreEqual("Two", kvPairs[0].Key);
|
||||
Assert.AreEqual("2", kvPairs[0].Value);
|
||||
Assert.AreEqual("One", kvPairs[1].Key);
|
||||
Assert.AreEqual("1", kvPairs[1].Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeClassWithInheritedProtectedMember()
|
||||
{
|
||||
AA myA = new AA(2);
|
||||
string json = JsonConvert.SerializeObject(myA, Formatting.Indented);
|
||||
Assert.AreEqual(@"{
|
||||
""AA_field1"": 2,
|
||||
""AA_property1"": 2,
|
||||
""AA_property2"": 2,
|
||||
""AA_property3"": 2,
|
||||
""AA_property4"": 2
|
||||
}", json);
|
||||
|
||||
BB myB = new BB(3, 4);
|
||||
json = JsonConvert.SerializeObject(myB, Formatting.Indented);
|
||||
Assert.AreEqual(@"{
|
||||
""BB_field1"": 4,
|
||||
""AA_field1"": 3,
|
||||
""BB_property1"": 4,
|
||||
""BB_property2"": 4,
|
||||
""BB_property3"": 4,
|
||||
""BB_property4"": 4,
|
||||
""BB_property5"": 4,
|
||||
""AA_property1"": 3,
|
||||
""AA_property2"": 3,
|
||||
""AA_property3"": 3,
|
||||
""AA_property4"": 3
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeClassWithInheritedProtectedMember()
|
||||
{
|
||||
AA myA = JsonConvert.DeserializeObject<AA>(
|
||||
@"{
|
||||
""AA_field1"": 2,
|
||||
""AA_property1"": 2,
|
||||
""AA_property2"": 2,
|
||||
""AA_property3"": 2,
|
||||
""AA_property4"": 2,
|
||||
""AA_property5"": 2,
|
||||
""AA_property6"": 2
|
||||
}");
|
||||
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myA));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myA));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myA));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myA));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myA));
|
||||
Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myA));
|
||||
Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myA));
|
||||
|
||||
BB myB = JsonConvert.DeserializeObject<BB>(
|
||||
@"{
|
||||
""BB_field1"": 4,
|
||||
""AA_field1"": 3,
|
||||
""AA_property1"": 2,
|
||||
""AA_property2"": 2,
|
||||
""AA_property3"": 2,
|
||||
""AA_property4"": 2,
|
||||
""AA_property5"": 2,
|
||||
""AA_property6"": 2,
|
||||
""BB_property1"": 3,
|
||||
""BB_property2"": 3,
|
||||
""BB_property3"": 3,
|
||||
""BB_property4"": 3,
|
||||
""BB_property5"": 3,
|
||||
""BB_property6"": 3
|
||||
}");
|
||||
|
||||
Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
|
||||
Assert.AreEqual(4, myB.BB_field1);
|
||||
Assert.AreEqual(3, myB.BB_property1);
|
||||
Assert.AreEqual(3, myB.BB_property2);
|
||||
Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property3", BindingFlags.Instance | BindingFlags.Public), myB));
|
||||
Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB));
|
||||
Assert.AreEqual(0, myB.BB_property5);
|
||||
Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property6", BindingFlags.Instance | BindingFlags.Public), myB));
|
||||
}
|
||||
|
||||
public class AA
|
||||
{
|
||||
[JsonProperty]
|
||||
protected int AA_field1;
|
||||
[JsonProperty]
|
||||
protected int AA_property1 { get; set; }
|
||||
[JsonProperty]
|
||||
protected int AA_property2 { get; private set; }
|
||||
[JsonProperty]
|
||||
protected int AA_property3 { private get; set; }
|
||||
[JsonProperty]
|
||||
private int AA_property4 { get; set; }
|
||||
protected int AA_property5 { get; private set; }
|
||||
protected int AA_property6 { private get; set; }
|
||||
|
||||
public AA()
|
||||
{
|
||||
}
|
||||
|
||||
public AA(int f)
|
||||
{
|
||||
AA_field1 = f;
|
||||
AA_property1 = f;
|
||||
AA_property2 = f;
|
||||
AA_property3 = f;
|
||||
AA_property4 = f;
|
||||
AA_property5 = f;
|
||||
AA_property6 = f;
|
||||
}
|
||||
}
|
||||
|
||||
public class BB : AA
|
||||
{
|
||||
[JsonProperty]
|
||||
public int BB_field1;
|
||||
[JsonProperty]
|
||||
public int BB_property1 { get; set; }
|
||||
[JsonProperty]
|
||||
public int BB_property2 { get; private set; }
|
||||
[JsonProperty]
|
||||
public int BB_property3 { private get; set; }
|
||||
[JsonProperty]
|
||||
private int BB_property4 { get; set; }
|
||||
public int BB_property5 { get; private set; }
|
||||
public int BB_property6 { private get; set; }
|
||||
|
||||
public BB()
|
||||
{
|
||||
}
|
||||
|
||||
public BB(int f, int g)
|
||||
: base(f)
|
||||
{
|
||||
BB_field1 = g;
|
||||
BB_property1 = g;
|
||||
BB_property2 = g;
|
||||
BB_property3 = g;
|
||||
BB_property4 = g;
|
||||
BB_property5 = g;
|
||||
BB_property6 = g;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -553,8 +553,18 @@ namespace Newtonsoft.Json.Serialization
|
||||
#endif
|
||||
));
|
||||
|
||||
property.Readable = ReflectionUtils.CanReadMemberValue(member);
|
||||
property.Writable = ReflectionUtils.CanSetMemberValue(member);
|
||||
bool allowNonPublicAccess = false;
|
||||
if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic)
|
||||
allowNonPublicAccess = true;
|
||||
if (propertyAttribute != null)
|
||||
allowNonPublicAccess = true;
|
||||
#if !PocketPC && !NET20
|
||||
if (dataMemberAttribute != null)
|
||||
allowNonPublicAccess = true;
|
||||
#endif
|
||||
|
||||
property.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess);
|
||||
property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess);
|
||||
|
||||
property.MemberConverter = JsonTypeReflector.GetJsonConverter(member, ReflectionUtils.GetMemberUnderlyingType(member));
|
||||
|
||||
|
||||
@@ -87,9 +87,9 @@ namespace Newtonsoft.Json.Serialization
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default creator.
|
||||
/// Gets or sets the default creator method used to create the object.
|
||||
/// </summary>
|
||||
/// <value>The default creator.</value>
|
||||
/// <value>The default creator method used to create the object.</value>
|
||||
public Func<object> DefaultCreator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -124,5 +124,16 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// </summary>
|
||||
/// <value>The object creation handling.</value>
|
||||
public ObjectCreationHandling? ObjectCreationHandling { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="String"/> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return PropertyName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,7 +655,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (contract.ISerializableCreator == null)
|
||||
throw new JsonSerializationException("ISerializable type '{0}' does not have a valid constructor.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
|
||||
object createdObject = contract.ISerializableCreator(new object[] { serializationInfo, Serializer.Context });
|
||||
object createdObject = contract.ISerializableCreator(serializationInfo, Serializer.Context);
|
||||
|
||||
if (id != null)
|
||||
Serializer.ReferenceResolver.AddReference(id, createdObject);
|
||||
|
||||
@@ -610,5 +610,19 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
return allAdded;
|
||||
}
|
||||
|
||||
public static int IndexOf<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (T value in collection)
|
||||
{
|
||||
if (predicate(value))
|
||||
return index;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,17 +489,30 @@ namespace Newtonsoft.Json.Utilities
|
||||
/// Determines whether the specified MemberInfo can be read.
|
||||
/// </summary>
|
||||
/// <param name="member">The MemberInfo to determine whether can be read.</param>
|
||||
/// /// <param name="nonPublic">if set to <c>true</c> then allow the member to be gotten non-publicly.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified MemberInfo can be read; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool CanReadMemberValue(MemberInfo member)
|
||||
public static bool CanReadMemberValue(MemberInfo member, bool nonPublic)
|
||||
{
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
return true;
|
||||
FieldInfo fieldInfo = (FieldInfo)member;
|
||||
|
||||
if (nonPublic)
|
||||
return true;
|
||||
else if (fieldInfo.IsPublic)
|
||||
return true;
|
||||
return false;
|
||||
case MemberTypes.Property:
|
||||
return ((PropertyInfo)member).CanRead;
|
||||
PropertyInfo propertyInfo = (PropertyInfo) member;
|
||||
|
||||
if (!propertyInfo.CanRead)
|
||||
return false;
|
||||
if (nonPublic)
|
||||
return true;
|
||||
return (propertyInfo.GetGetMethod(nonPublic) != null);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -509,17 +522,32 @@ namespace Newtonsoft.Json.Utilities
|
||||
/// Determines whether the specified MemberInfo can be set.
|
||||
/// </summary>
|
||||
/// <param name="member">The MemberInfo to determine whether can be set.</param>
|
||||
/// <param name="nonPublic">if set to <c>true</c> then allow the member to be set non-publicly.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool CanSetMemberValue(MemberInfo member)
|
||||
public static bool CanSetMemberValue(MemberInfo member, bool nonPublic)
|
||||
{
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
return !((FieldInfo)member).IsInitOnly;
|
||||
FieldInfo fieldInfo = (FieldInfo)member;
|
||||
|
||||
if (fieldInfo.IsInitOnly)
|
||||
return false;
|
||||
if (nonPublic)
|
||||
return true;
|
||||
else if (fieldInfo.IsPublic)
|
||||
return true;
|
||||
return false;
|
||||
case MemberTypes.Property:
|
||||
return ((PropertyInfo)member).CanWrite;
|
||||
PropertyInfo propertyInfo = (PropertyInfo)member;
|
||||
|
||||
if (!propertyInfo.CanWrite)
|
||||
return false;
|
||||
if (nonPublic)
|
||||
return true;
|
||||
return (propertyInfo.GetSetMethod(nonPublic) != null);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -540,6 +568,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
// for some reason .NET returns multiple members when overriding a generic member on a base class
|
||||
// http://forums.msdn.microsoft.com/en-US/netfxbcl/thread/b5abbfee-e292-4a64-8907-4e3f0fb90cd9/
|
||||
// filter members to only return the override on the topmost class
|
||||
// update: I think this is fixed in .NET 3.5 SP1 - leave this in for now...
|
||||
List<MemberInfo> distinctMembers = new List<MemberInfo>(targetMembers.Count);
|
||||
|
||||
var groupedMembers = targetMembers.GroupBy(m => m.Name).Select(g => new { Count = g.Count(), Members = g.Cast<MemberInfo>() });
|
||||
@@ -655,6 +684,9 @@ namespace Newtonsoft.Json.Utilities
|
||||
#if !PocketPC
|
||||
return Activator.CreateInstance(type, args);
|
||||
#else
|
||||
// CF doesn't have a Activator.CreateInstance overload that takes args
|
||||
// lame
|
||||
|
||||
if (type.IsValueType)
|
||||
return Activator.CreateInstance(type);
|
||||
|
||||
@@ -732,6 +764,8 @@ namespace Newtonsoft.Json.Utilities
|
||||
ValidationUtils.ArgumentNotNull(targetType, "targetType");
|
||||
|
||||
List<MemberInfo> fieldInfos = new List<MemberInfo>(targetType.GetFields(bindingAttr));
|
||||
// Type.GetFields doesn't return inherited private fields
|
||||
// manually find private fields from base class
|
||||
GetChildPrivateFields(fieldInfos, targetType, bindingAttr);
|
||||
|
||||
return fieldInfos.Cast<FieldInfo>();
|
||||
@@ -739,18 +773,20 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
private static void GetChildPrivateFields(IList<MemberInfo> initialFields, Type targetType, BindingFlags bindingAttr)
|
||||
{
|
||||
// fix weirdness with FieldInfos only being returned for the current Type
|
||||
// fix weirdness with private FieldInfos only being returned for the current Type
|
||||
// find base type fields and add them to result
|
||||
if ((bindingAttr & BindingFlags.NonPublic) != 0)
|
||||
{
|
||||
// modify flags to not search for public fields
|
||||
BindingFlags nonPublicBindingAttr = ((bindingAttr & BindingFlags.Public) == BindingFlags.Public)
|
||||
? bindingAttr ^ BindingFlags.Public
|
||||
: bindingAttr;
|
||||
BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
|
||||
|
||||
while ((targetType = targetType.BaseType) != null)
|
||||
{
|
||||
initialFields.AddRange(targetType.GetFields(nonPublicBindingAttr));
|
||||
// filter out protected fields
|
||||
IEnumerable<MemberInfo> childPrivateFields =
|
||||
targetType.GetFields(nonPublicBindingAttr).Where(f => f.IsPrivate).Cast<MemberInfo>();
|
||||
|
||||
initialFields.AddRange(childPrivateFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -765,20 +801,43 @@ namespace Newtonsoft.Json.Utilities
|
||||
return propertyInfos.Cast<PropertyInfo>();
|
||||
}
|
||||
|
||||
private static void GetChildPrivateProperties(IList<MemberInfo> initialFields, Type targetType, BindingFlags bindingAttr)
|
||||
public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag)
|
||||
{
|
||||
// fix weirdness with FieldInfos only being returned for the current Type
|
||||
// find base type fields and add them to result
|
||||
return ((bindingAttr & flag) == flag)
|
||||
? bindingAttr ^ flag
|
||||
: bindingAttr;
|
||||
}
|
||||
|
||||
private static void GetChildPrivateProperties(IList<MemberInfo> 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
|
||||
if ((bindingAttr & BindingFlags.NonPublic) != 0)
|
||||
{
|
||||
// modify flags to not search for public fields
|
||||
BindingFlags nonPublicBindingAttr = ((bindingAttr & BindingFlags.Public) == BindingFlags.Public)
|
||||
? bindingAttr ^ BindingFlags.Public
|
||||
: bindingAttr;
|
||||
BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
|
||||
|
||||
while ((targetType = targetType.BaseType) != null)
|
||||
{
|
||||
initialFields.AddRange(targetType.GetProperties(nonPublicBindingAttr));
|
||||
foreach (PropertyInfo propertyInfo in targetType.GetProperties(nonPublicBindingAttr))
|
||||
{
|
||||
PropertyInfo nonPublicProperty = propertyInfo;
|
||||
|
||||
// have to test on name rather than reference because instances are different
|
||||
// depending on the type that GetProperties was called on
|
||||
int index = initialProperties.IndexOf(p => p.Name == nonPublicProperty.Name);
|
||||
if (index == -1)
|
||||
{
|
||||
initialProperties.Add(nonPublicProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
// replace nonpublic properties for a child, but gotten from
|
||||
// the parent with the one from the child
|
||||
// the property gotten from the child will have access to private getter/setter
|
||||
initialProperties[index] = nonPublicProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user