-Fixed hiding generic properties sometimes not being detected
This commit is contained in:
@@ -75,4 +75,4 @@ using System.Security;
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("6.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("6.0.1.17115")]
|
||||
[assembly: AssemblyFileVersion("6.0.1.17117")]
|
||||
|
||||
@@ -306,6 +306,110 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
Assert.AreEqual(true, childClass.IsTransient);
|
||||
}
|
||||
|
||||
public class ResponseWithNewGenericProperty<T> : SimpleResponse
|
||||
{
|
||||
public new T Data { get; set; }
|
||||
}
|
||||
|
||||
public class ResponseWithNewGenericPropertyVirtual<T> : SimpleResponse
|
||||
{
|
||||
public virtual new T Data { get; set; }
|
||||
}
|
||||
|
||||
public class ResponseWithNewGenericPropertyOverride<T> : ResponseWithNewGenericPropertyVirtual<T>
|
||||
{
|
||||
public override T Data { get; set; }
|
||||
}
|
||||
|
||||
public abstract class SimpleResponse
|
||||
{
|
||||
public string Result { get; set; }
|
||||
public string Message { get; set; }
|
||||
public object Data { get; set; }
|
||||
|
||||
protected SimpleResponse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected SimpleResponse(string message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSerializeWithBuiltInTypeAsGenericArgument()
|
||||
{
|
||||
var input = new ResponseWithNewGenericProperty<int>()
|
||||
{
|
||||
Message = "Trying out integer as type parameter",
|
||||
Data = 25,
|
||||
Result = "This should be fine"
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(input);
|
||||
var deserialized = JsonConvert.DeserializeObject<ResponseWithNewGenericProperty<int>>(json);
|
||||
|
||||
Assert.AreEqual(input.Data, deserialized.Data);
|
||||
Assert.AreEqual(input.Message, deserialized.Message);
|
||||
Assert.AreEqual(input.Result, deserialized.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSerializeWithBuiltInTypeAsGenericArgumentVirtual()
|
||||
{
|
||||
var input = new ResponseWithNewGenericPropertyVirtual<int>()
|
||||
{
|
||||
Message = "Trying out integer as type parameter",
|
||||
Data = 25,
|
||||
Result = "This should be fine"
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(input);
|
||||
var deserialized = JsonConvert.DeserializeObject<ResponseWithNewGenericPropertyVirtual<int>>(json);
|
||||
|
||||
Assert.AreEqual(input.Data, deserialized.Data);
|
||||
Assert.AreEqual(input.Message, deserialized.Message);
|
||||
Assert.AreEqual(input.Result, deserialized.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSerializeWithBuiltInTypeAsGenericArgumentOverride()
|
||||
{
|
||||
var input = new ResponseWithNewGenericPropertyOverride<int>()
|
||||
{
|
||||
Message = "Trying out integer as type parameter",
|
||||
Data = 25,
|
||||
Result = "This should be fine"
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(input);
|
||||
var deserialized = JsonConvert.DeserializeObject<ResponseWithNewGenericPropertyOverride<int>>(json);
|
||||
|
||||
Assert.AreEqual(input.Data, deserialized.Data);
|
||||
Assert.AreEqual(input.Message, deserialized.Message);
|
||||
Assert.AreEqual(input.Result, deserialized.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSerializedWithGenericClosedTypeAsArgument()
|
||||
{
|
||||
var input = new ResponseWithNewGenericProperty<List<int>>()
|
||||
{
|
||||
Message = "More complex case - generic list of int",
|
||||
Data = Enumerable.Range(50, 70).ToList(),
|
||||
Result = "This should be fine too"
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(input);
|
||||
var deserialized = JsonConvert.DeserializeObject<ResponseWithNewGenericProperty<List<int>>>(json);
|
||||
|
||||
Assert.AreEqual(input.Data, deserialized.Data);
|
||||
Assert.AreEqual(input.Message, deserialized.Message);
|
||||
Assert.AreEqual(input.Result, deserialized.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonSerializerProperties()
|
||||
{
|
||||
|
||||
@@ -91,5 +91,5 @@ using System.Security;
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("6.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("6.0.1.17115")]
|
||||
[assembly: AssemblyFileVersion("6.0.1.17117")]
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
@@ -597,7 +597,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
targetMembers.AddRange(GetProperties(type, bindingAttr));
|
||||
|
||||
// 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/
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/b5abbfee-e292-4a64-8907-4e3f0fb90cd9/reflection-overriden-abstract-generic-properties?forum=netfxbcl
|
||||
// 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);
|
||||
@@ -613,7 +613,14 @@ namespace Newtonsoft.Json.Utilities
|
||||
}
|
||||
else
|
||||
{
|
||||
var resolvedMembers = members.Where(m => !IsOverridenGenericMember(m, bindingAttr) || m.Name == "Item");
|
||||
IList<MemberInfo> resolvedMembers = new List<MemberInfo>();
|
||||
foreach (MemberInfo memberInfo in members)
|
||||
{
|
||||
if (resolvedMembers.Count == 0)
|
||||
resolvedMembers.Add(memberInfo);
|
||||
else if (!IsOverridenGenericMember(memberInfo, bindingAttr) || memberInfo.Name == "Item")
|
||||
resolvedMembers.Add(memberInfo);
|
||||
}
|
||||
|
||||
distinctMembers.AddRange(resolvedMembers);
|
||||
}
|
||||
@@ -622,20 +629,22 @@ namespace Newtonsoft.Json.Utilities
|
||||
return distinctMembers;
|
||||
}
|
||||
|
||||
|
||||
private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr)
|
||||
{
|
||||
MemberTypes memberType = memberInfo.MemberType();
|
||||
if (memberType != MemberTypes.Field && memberType != MemberTypes.Property)
|
||||
throw new ArgumentException("Member must be a field or property.");
|
||||
if (memberInfo.MemberType() != MemberTypes.Property)
|
||||
return false;
|
||||
|
||||
Type declaringType = memberInfo.DeclaringType;
|
||||
PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
|
||||
if (!IsVirtual(propertyInfo))
|
||||
return false;
|
||||
|
||||
Type declaringType = propertyInfo.DeclaringType;
|
||||
if (!declaringType.IsGenericType())
|
||||
return false;
|
||||
Type genericTypeDefinition = declaringType.GetGenericTypeDefinition();
|
||||
if (genericTypeDefinition == null)
|
||||
return false;
|
||||
MemberInfo[] members = genericTypeDefinition.GetMember(memberInfo.Name, bindingAttr);
|
||||
MemberInfo[] members = genericTypeDefinition.GetMember(propertyInfo.Name, bindingAttr);
|
||||
if (members.Length == 0)
|
||||
return false;
|
||||
Type memberUnderlyingType = GetMemberUnderlyingType(members[0]);
|
||||
|
||||
Reference in New Issue
Block a user