-Fixed error when populating onto read only collections
-Fixed serializing hidden properties -Readded DataContractAttribute inheritance
This commit is contained in:
@@ -75,4 +75,4 @@ using System.Security;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("4.5.0.0")]
|
||||
[assembly: AssemblyFileVersion("5.0.1.16006")]
|
||||
[assembly: AssemblyFileVersion("5.0.1.16007")]
|
||||
|
||||
@@ -90,39 +90,245 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
[TestFixture]
|
||||
public class JsonSerializerTest : TestFixtureBase
|
||||
{
|
||||
//[DataContract]
|
||||
//public class BaseDataContract1
|
||||
//{
|
||||
// [DataMember(Name = "virtualMember")]
|
||||
// public virtual string VirtualMember { get; set; }
|
||||
#if !NET20
|
||||
[DataContract]
|
||||
public class BaseDataContractWithHidden
|
||||
{
|
||||
[DataMember(Name = "virtualMember")]
|
||||
public virtual string VirtualMember { get; set; }
|
||||
|
||||
// [DataMember(Name = "nonVirtualMember")]
|
||||
// public string NonVirtualMember { get; set; }
|
||||
[DataMember(Name = "nonVirtualMember")]
|
||||
public string NonVirtualMember { get; set; }
|
||||
|
||||
// public virtual object NewMember { get; set; }
|
||||
//}
|
||||
public virtual object NewMember { get; set; }
|
||||
}
|
||||
|
||||
//public class ChildDataContract1 : BaseDataContract1
|
||||
//{
|
||||
// [DataMember(Name = "NewMember")]
|
||||
// public virtual new string NewMember { get; set; }
|
||||
// public override string VirtualMember { get; set; }
|
||||
// public string AddedMember { get; set; }
|
||||
//}
|
||||
public class ChildDataContractWithHidden : BaseDataContractWithHidden
|
||||
{
|
||||
[DataMember(Name = "NewMember")]
|
||||
public virtual new string NewMember { get; set; }
|
||||
public override string VirtualMember { get; set; }
|
||||
public string AddedMember { get; set; }
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void ChildDataContractTest1()
|
||||
//{
|
||||
// var cc = new ChildDataContract1
|
||||
// {
|
||||
// VirtualMember = "VirtualMember!",
|
||||
// NonVirtualMember = "NonVirtualMember!",
|
||||
// NewMember = "NewMember!"
|
||||
// };
|
||||
[Test]
|
||||
public void ChildDataContractTestWithHidden()
|
||||
{
|
||||
var cc = new ChildDataContractWithHidden
|
||||
{
|
||||
VirtualMember = "VirtualMember!",
|
||||
NonVirtualMember = "NonVirtualMember!",
|
||||
NewMember = "NewMember!"
|
||||
};
|
||||
|
||||
// string result = JsonConvert.SerializeObject(cc);
|
||||
// Assert.AreEqual(@"{""NewMember"":""NewMember!"",""virtualMember"":""VirtualMember!"",""nonVirtualMember"":""NonVirtualMember!""}", result);
|
||||
//}
|
||||
string result = JsonConvert.SerializeObject(cc);
|
||||
Assert.AreEqual(@"{""NewMember"":""NewMember!"",""virtualMember"":""VirtualMember!"",""nonVirtualMember"":""NonVirtualMember!""}", result);
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseWithContract
|
||||
{
|
||||
[DataMember(Name = "VirtualWithDataMemberBase")]
|
||||
public virtual string VirtualWithDataMember { get; set; }
|
||||
[DataMember]
|
||||
public virtual string Virtual { get; set; }
|
||||
[DataMember(Name = "WithDataMemberBase")]
|
||||
public string WithDataMember { get; set; }
|
||||
[DataMember]
|
||||
public string JustAProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseWithoutContract
|
||||
{
|
||||
[DataMember(Name = "VirtualWithDataMemberBase")]
|
||||
public virtual string VirtualWithDataMember { get; set; }
|
||||
[DataMember]
|
||||
public virtual string Virtual { get; set; }
|
||||
[DataMember(Name = "WithDataMemberBase")]
|
||||
public string WithDataMember { get; set; }
|
||||
[DataMember]
|
||||
public string JustAProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SubWithoutContractNewProperties : BaseWithContract
|
||||
{
|
||||
[DataMember(Name = "VirtualWithDataMemberSub")]
|
||||
public string VirtualWithDataMember { get; set; }
|
||||
public string Virtual { get; set; }
|
||||
[DataMember(Name = "WithDataMemberSub")]
|
||||
public string WithDataMember { get; set; }
|
||||
public string JustAProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SubWithoutContractVirtualProperties : BaseWithContract
|
||||
{
|
||||
public override string VirtualWithDataMember { get; set; }
|
||||
[DataMember(Name = "VirtualSub")]
|
||||
public override string Virtual { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SubWithContractNewProperties : BaseWithContract
|
||||
{
|
||||
[DataMember(Name = "VirtualWithDataMemberSub")]
|
||||
public string VirtualWithDataMember { get; set; }
|
||||
[DataMember(Name = "Virtual2")]
|
||||
public string Virtual { get; set; }
|
||||
[DataMember(Name = "WithDataMemberSub")]
|
||||
public string WithDataMember { get; set; }
|
||||
[DataMember(Name = "JustAProperty2")]
|
||||
public string JustAProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SubWithContractVirtualProperties : BaseWithContract
|
||||
{
|
||||
[DataMember(Name = "VirtualWithDataMemberSub")]
|
||||
public virtual string VirtualWithDataMember { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubWithoutContractNewPropertiesTest()
|
||||
{
|
||||
BaseWithContract baseWith = new SubWithoutContractNewProperties
|
||||
{
|
||||
JustAProperty = "JustAProperty!",
|
||||
Virtual = "Virtual!",
|
||||
VirtualWithDataMember = "VirtualWithDataMember!",
|
||||
WithDataMember = "WithDataMember!"
|
||||
};
|
||||
|
||||
baseWith.JustAProperty = "JustAProperty2!";
|
||||
baseWith.Virtual = "Virtual2!";
|
||||
baseWith.VirtualWithDataMember = "VirtualWithDataMember2!";
|
||||
baseWith.WithDataMember = "WithDataMember2!";
|
||||
|
||||
string json = AssertSerializeDeserializeEqual(baseWith);
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""JustAProperty"": ""JustAProperty2!"",
|
||||
""Virtual"": ""Virtual2!"",
|
||||
""VirtualWithDataMemberBase"": ""VirtualWithDataMember2!"",
|
||||
""VirtualWithDataMemberSub"": ""VirtualWithDataMember!"",
|
||||
""WithDataMemberBase"": ""WithDataMember2!"",
|
||||
""WithDataMemberSub"": ""WithDataMember!""
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubWithoutContractVirtualPropertiesTest()
|
||||
{
|
||||
BaseWithContract baseWith = new SubWithoutContractVirtualProperties
|
||||
{
|
||||
JustAProperty = "JustAProperty!",
|
||||
Virtual = "Virtual!",
|
||||
VirtualWithDataMember = "VirtualWithDataMember!",
|
||||
WithDataMember = "WithDataMember!"
|
||||
};
|
||||
|
||||
baseWith.JustAProperty = "JustAProperty2!";
|
||||
baseWith.Virtual = "Virtual2!";
|
||||
baseWith.VirtualWithDataMember = "VirtualWithDataMember2!";
|
||||
baseWith.WithDataMember = "WithDataMember2!";
|
||||
|
||||
string json = JsonConvert.SerializeObject(baseWith, Formatting.Indented);
|
||||
|
||||
Console.WriteLine(json);
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""VirtualWithDataMemberBase"": ""VirtualWithDataMember2!"",
|
||||
""VirtualSub"": ""Virtual2!"",
|
||||
""WithDataMemberBase"": ""WithDataMember2!"",
|
||||
""JustAProperty"": ""JustAProperty2!""
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubWithContractNewPropertiesTest()
|
||||
{
|
||||
BaseWithContract baseWith = new SubWithContractNewProperties
|
||||
{
|
||||
JustAProperty = "JustAProperty!",
|
||||
Virtual = "Virtual!",
|
||||
VirtualWithDataMember = "VirtualWithDataMember!",
|
||||
WithDataMember = "WithDataMember!"
|
||||
};
|
||||
|
||||
baseWith.JustAProperty = "JustAProperty2!";
|
||||
baseWith.Virtual = "Virtual2!";
|
||||
baseWith.VirtualWithDataMember = "VirtualWithDataMember2!";
|
||||
baseWith.WithDataMember = "WithDataMember2!";
|
||||
|
||||
string json = AssertSerializeDeserializeEqual(baseWith);
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""JustAProperty"": ""JustAProperty2!"",
|
||||
""JustAProperty2"": ""JustAProperty!"",
|
||||
""Virtual"": ""Virtual2!"",
|
||||
""Virtual2"": ""Virtual!"",
|
||||
""VirtualWithDataMemberBase"": ""VirtualWithDataMember2!"",
|
||||
""VirtualWithDataMemberSub"": ""VirtualWithDataMember!"",
|
||||
""WithDataMemberBase"": ""WithDataMember2!"",
|
||||
""WithDataMemberSub"": ""WithDataMember!""
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubWithContractVirtualPropertiesTest()
|
||||
{
|
||||
BaseWithContract baseWith = new SubWithContractVirtualProperties
|
||||
{
|
||||
JustAProperty = "JustAProperty!",
|
||||
Virtual = "Virtual!",
|
||||
VirtualWithDataMember = "VirtualWithDataMember!",
|
||||
WithDataMember = "WithDataMember!"
|
||||
};
|
||||
|
||||
baseWith.JustAProperty = "JustAProperty2!";
|
||||
baseWith.Virtual = "Virtual2!";
|
||||
baseWith.VirtualWithDataMember = "VirtualWithDataMember2!";
|
||||
baseWith.WithDataMember = "WithDataMember2!";
|
||||
|
||||
string json = AssertSerializeDeserializeEqual(baseWith);
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""JustAProperty"": ""JustAProperty2!"",
|
||||
""Virtual"": ""Virtual2!"",
|
||||
""VirtualWithDataMemberBase"": ""VirtualWithDataMember2!"",
|
||||
""VirtualWithDataMemberSub"": ""VirtualWithDataMember!"",
|
||||
""WithDataMemberBase"": ""WithDataMember2!""
|
||||
}", json);
|
||||
}
|
||||
|
||||
private string AssertSerializeDeserializeEqual(object o)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
DataContractJsonSerializer s = new DataContractJsonSerializer(o.GetType());
|
||||
s.WriteObject(ms, o);
|
||||
|
||||
var data = ms.ToArray();
|
||||
JObject dataContractJson = JObject.Parse(Encoding.UTF8.GetString(data, 0, data.Length));
|
||||
dataContractJson = new JObject(dataContractJson.Properties().OrderBy(p => p.Name));
|
||||
|
||||
JObject jsonNetJson = JObject.Parse(JsonConvert.SerializeObject(o));
|
||||
jsonNetJson = new JObject(jsonNetJson.Properties().OrderBy(p => p.Name));
|
||||
|
||||
Console.WriteLine("Results for " + o.GetType().Name);
|
||||
Console.WriteLine("DataContractJsonSerializer: " + dataContractJson);
|
||||
Console.WriteLine("JsonDotNetSerializer : " + jsonNetJson);
|
||||
|
||||
Assert.AreEqual(dataContractJson.Count, jsonNetJson.Count);
|
||||
foreach (KeyValuePair<string, JToken> property in dataContractJson)
|
||||
{
|
||||
Assert.IsTrue(JToken.DeepEquals(jsonNetJson[property.Key], property.Value), "Property not equal: " + property.Key);
|
||||
}
|
||||
|
||||
return jsonNetJson.ToString();
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void PersonTypedObjectDeserialization()
|
||||
@@ -5078,6 +5284,7 @@ To fix this error either change the environment to be fully trusted, change the
|
||||
};
|
||||
|
||||
string result = JsonConvert.SerializeObject(cc);
|
||||
Console.WriteLine(result);
|
||||
Assert.AreEqual(@"{""differentVirtualMember"":""VirtualMember!"",""nonVirtualMember"":""NonVirtualMember!""}", result);
|
||||
}
|
||||
|
||||
@@ -7018,6 +7225,134 @@ Parameter name: value",
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !(NET40 || NET35 || NET20 || SILVERLIGHT || WINDOWS_PHONE || PORTABLE40)
|
||||
public class PopulateReadOnlyTestClass
|
||||
{
|
||||
public IList<int> NonReadOnlyList { get; set; }
|
||||
public IDictionary<string, int> NonReadOnlyDictionary { get; set; }
|
||||
|
||||
public IList<int> Array { get; set; }
|
||||
|
||||
public IList<int> List { get; set; }
|
||||
public IDictionary<string, int> Dictionary { get; set; }
|
||||
|
||||
public IReadOnlyCollection<int> IReadOnlyCollection { get; set; }
|
||||
public ReadOnlyCollection<int> ReadOnlyCollection { get; set; }
|
||||
public IReadOnlyList<int> IReadOnlyList { get; set; }
|
||||
|
||||
public IReadOnlyDictionary<string, int> IReadOnlyDictionary { get; set; }
|
||||
public ReadOnlyDictionary<string, int> ReadOnlyDictionary { get; set; }
|
||||
|
||||
public PopulateReadOnlyTestClass()
|
||||
{
|
||||
NonReadOnlyList = new List<int> { 1 };
|
||||
NonReadOnlyDictionary = new Dictionary<string, int> { { "first", 2 } };
|
||||
|
||||
Array = new[] {3};
|
||||
|
||||
List = new ReadOnlyCollection<int>(new[] { 4 });
|
||||
Dictionary = new ReadOnlyDictionary<string, int>(new Dictionary<string, int> { { "first", 5 } });
|
||||
|
||||
IReadOnlyCollection = new ReadOnlyCollection<int>(new[] { 6 });
|
||||
ReadOnlyCollection = new ReadOnlyCollection<int>(new[] { 7 });
|
||||
IReadOnlyList = new ReadOnlyCollection<int>(new[] { 8 });
|
||||
|
||||
IReadOnlyDictionary = new ReadOnlyDictionary<string, int>(new Dictionary<string, int> { { "first", 9 } });
|
||||
ReadOnlyDictionary = new ReadOnlyDictionary<string, int>(new Dictionary<string, int> { { "first", 10 } });
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeReadOnlyCollections()
|
||||
{
|
||||
PopulateReadOnlyTestClass c1 = new PopulateReadOnlyTestClass();
|
||||
|
||||
string json = JsonConvert.SerializeObject(c1, Formatting.Indented);
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""NonReadOnlyList"": [
|
||||
1
|
||||
],
|
||||
""NonReadOnlyDictionary"": {
|
||||
""first"": 2
|
||||
},
|
||||
""Array"": [
|
||||
3
|
||||
],
|
||||
""List"": [
|
||||
4
|
||||
],
|
||||
""Dictionary"": {
|
||||
""first"": 5
|
||||
},
|
||||
""IReadOnlyCollection"": [
|
||||
6
|
||||
],
|
||||
""ReadOnlyCollection"": [
|
||||
7
|
||||
],
|
||||
""IReadOnlyList"": [
|
||||
8
|
||||
],
|
||||
""IReadOnlyDictionary"": {
|
||||
""first"": 9
|
||||
},
|
||||
""ReadOnlyDictionary"": {
|
||||
""first"": 10
|
||||
}
|
||||
}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PopulateReadOnlyCollections()
|
||||
{
|
||||
string json = @"{
|
||||
""NonReadOnlyList"": [
|
||||
11
|
||||
],
|
||||
""NonReadOnlyDictionary"": {
|
||||
""first"": 12
|
||||
},
|
||||
""Array"": [
|
||||
13
|
||||
],
|
||||
""List"": [
|
||||
14
|
||||
],
|
||||
""Dictionary"": {
|
||||
""first"": 15
|
||||
},
|
||||
""IReadOnlyCollection"": [
|
||||
16
|
||||
],
|
||||
""ReadOnlyCollection"": [
|
||||
17
|
||||
],
|
||||
""IReadOnlyList"": [
|
||||
18
|
||||
],
|
||||
""IReadOnlyDictionary"": {
|
||||
""first"": 19
|
||||
},
|
||||
""ReadOnlyDictionary"": {
|
||||
""first"": 20
|
||||
}
|
||||
}";
|
||||
|
||||
var c2 = JsonConvert.DeserializeObject<PopulateReadOnlyTestClass>(json);
|
||||
|
||||
Assert.AreEqual(1, c2.NonReadOnlyDictionary.Count);
|
||||
Assert.AreEqual(12, c2.NonReadOnlyDictionary["first"]);
|
||||
|
||||
Assert.AreEqual(2, c2.NonReadOnlyList.Count);
|
||||
Assert.AreEqual(1, c2.NonReadOnlyList[0]);
|
||||
Assert.AreEqual(11, c2.NonReadOnlyList[1]);
|
||||
|
||||
Assert.AreEqual(1, c2.Array.Count);
|
||||
Assert.AreEqual(13, c2.Array[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void SerializeArray2D()
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ using System.IO;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Runtime.Serialization.Json;
|
||||
#endif
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -53,6 +55,18 @@ namespace Newtonsoft.Json.Tests
|
||||
[TestFixture]
|
||||
public abstract class TestFixtureBase
|
||||
{
|
||||
#if !NET20
|
||||
protected string GetDataContractJsonSerializeResult(object o)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
DataContractJsonSerializer s = new DataContractJsonSerializer(o.GetType());
|
||||
s.WriteObject(ms, o);
|
||||
|
||||
var data = ms.ToArray();
|
||||
return Encoding.UTF8.GetString(data, 0, data.Length);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected string GetOffset(DateTime d, DateFormatHandling dateFormatHandling)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
|
||||
@@ -92,6 +92,6 @@ using System.Security;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("4.5.0.0")]
|
||||
[assembly: AssemblyFileVersion("5.0.1.16006")]
|
||||
[assembly: AssemblyFileVersion("5.0.1.16007")]
|
||||
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
@@ -1025,8 +1025,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (memberSerialization != MemberSerialization.OptIn)
|
||||
{
|
||||
bool hasIgnoreDataMemberAttribute = false;
|
||||
|
||||
bool hasIgnoreDataMemberAttribute = false;
|
||||
|
||||
#if !(NET20 || NET35)
|
||||
hasIgnoreDataMemberAttribute = (JsonTypeReflector.GetAttribute<IgnoreDataMemberAttribute>(attributeProvider) != null);
|
||||
#endif
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (CollectionItemType != null)
|
||||
ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
|
||||
|
||||
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>));
|
||||
canDeserialize = true;
|
||||
}
|
||||
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
|
||||
|
||||
@@ -89,6 +89,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IDictionary<,>)))
|
||||
CreatedType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
|
||||
|
||||
#if !(NET40 || NET35 || NET20 || SILVERLIGHT || WINDOWS_PHONE || PORTABLE40)
|
||||
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyDictionary<,>));
|
||||
#endif
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || SILVERLIGHT || WINDOWS_PHONE || PORTABLE40)
|
||||
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IReadOnlyDictionary<,>), out _genericCollectionDefinitionType))
|
||||
|
||||
@@ -81,19 +81,21 @@ namespace Newtonsoft.Json.Serialization
|
||||
Remove(existingProperty);
|
||||
duplicateProperty = false;
|
||||
}
|
||||
|
||||
if (property.DeclaringType != null && existingProperty.DeclaringType != null)
|
||||
else
|
||||
{
|
||||
if (property.DeclaringType.IsSubclassOf(existingProperty.DeclaringType))
|
||||
if (property.DeclaringType != null && existingProperty.DeclaringType != null)
|
||||
{
|
||||
// current property is on a derived class and hides the existing
|
||||
Remove(existingProperty);
|
||||
duplicateProperty = false;
|
||||
}
|
||||
if (existingProperty.DeclaringType.IsSubclassOf(property.DeclaringType))
|
||||
{
|
||||
// current property is hidden by the existing so don't add it
|
||||
return;
|
||||
if (property.DeclaringType.IsSubclassOf(existingProperty.DeclaringType))
|
||||
{
|
||||
// current property is on a derived class and hides the existing
|
||||
Remove(existingProperty);
|
||||
duplicateProperty = false;
|
||||
}
|
||||
if (existingProperty.DeclaringType.IsSubclassOf(property.DeclaringType))
|
||||
{
|
||||
// current property is hidden by the existing so don't add it
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -791,7 +791,12 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
currentValue = property.ValueProvider.GetValue(target);
|
||||
gottenCurrentValue = true;
|
||||
|
||||
useExistingValue = (currentValue != null && !property.PropertyContract.IsReadOnlyOrFixedSize && !property.PropertyType.IsValueType());
|
||||
if (currentValue != null)
|
||||
{
|
||||
propertyContract = GetContractSafe(currentValue.GetType());
|
||||
|
||||
useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType());
|
||||
}
|
||||
}
|
||||
|
||||
if (!property.Writable && !useExistingValue)
|
||||
|
||||
@@ -119,7 +119,18 @@ namespace Newtonsoft.Json.Serialization
|
||||
public static DataContractAttribute GetDataContractAttribute(Type type)
|
||||
{
|
||||
// DataContractAttribute does not have inheritance
|
||||
return CachedAttributeGetter<DataContractAttribute>.GetAttribute(type);
|
||||
Type currentType = type;
|
||||
|
||||
while (currentType != null)
|
||||
{
|
||||
DataContractAttribute result = CachedAttributeGetter<DataContractAttribute>.GetAttribute(currentType);
|
||||
if (result != null)
|
||||
return result;
|
||||
|
||||
currentType = currentType.BaseType();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DataMemberAttribute GetDataMemberAttribute(MemberInfo memberInfo)
|
||||
|
||||
@@ -109,6 +109,31 @@ namespace Newtonsoft.Json.Utilities
|
||||
return false;
|
||||
}
|
||||
|
||||
public static MethodInfo GetBaseDefinition(this PropertyInfo propertyInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
|
||||
|
||||
MethodInfo m = propertyInfo.GetGetMethod();
|
||||
if (m != null)
|
||||
return m.GetBaseDefinition();
|
||||
|
||||
m = propertyInfo.GetSetMethod();
|
||||
if (m != null)
|
||||
return m.GetBaseDefinition();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool IsPublic(PropertyInfo property)
|
||||
{
|
||||
if (property.GetGetMethod() != null && property.GetGetMethod().IsPublic)
|
||||
return true;
|
||||
if (property.GetSetMethod() != null && property.GetSetMethod().IsPublic)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Type GetObjectType(object v)
|
||||
{
|
||||
return (v != null) ? v.GetType() : null;
|
||||
@@ -812,30 +837,51 @@ namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
// 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)
|
||||
|
||||
// also find base properties that have been hidden by subtype properties with the same name
|
||||
|
||||
while ((targetType = targetType.BaseType()) != null)
|
||||
{
|
||||
// modify flags to not search for public fields
|
||||
BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
|
||||
|
||||
while ((targetType = targetType.BaseType()) != null)
|
||||
foreach (PropertyInfo propertyInfo in targetType.GetProperties(bindingAttr))
|
||||
{
|
||||
foreach (PropertyInfo propertyInfo in targetType.GetProperties(nonPublicBindingAttr))
|
||||
{
|
||||
PropertyInfo nonPublicProperty = propertyInfo;
|
||||
PropertyInfo subTypeProperty = propertyInfo;
|
||||
|
||||
if (!IsPublic(subTypeProperty))
|
||||
{
|
||||
// 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);
|
||||
int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name);
|
||||
if (index == -1)
|
||||
{
|
||||
initialProperties.Add(nonPublicProperty);
|
||||
initialProperties.Add(subTypeProperty);
|
||||
}
|
||||
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;
|
||||
initialProperties[index] = subTypeProperty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!subTypeProperty.IsVirtual())
|
||||
{
|
||||
int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name
|
||||
&& p.DeclaringType == subTypeProperty.DeclaringType);
|
||||
|
||||
if (index == -1)
|
||||
initialProperties.Add(subTypeProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name
|
||||
&& p.IsVirtual()
|
||||
&& p.GetBaseDefinition() != null
|
||||
&& p.GetBaseDefinition().DeclaringType.IsAssignableFrom(subTypeProperty.DeclaringType));
|
||||
|
||||
if (index == -1)
|
||||
initialProperties.Add(subTypeProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user