Json.NET의 의도 된 동작처럼 보입니다. ReflectionUtils.cs에서 :
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
// also find base properties that have been hidden by subtype properties with the same name
while ((targetType = targetType.BaseType()) != null)
{
foreach (PropertyInfo propertyInfo in targetType.GetProperties(bindingAttr))
{
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 == subTypeProperty.Name);
if (index == -1)
{
initialProperties.Add(subTypeProperty);
}
else
{
PropertyInfo childProperty = initialProperties[index];
// don't replace public child with private base
if (!IsPublic(childProperty))
{
// 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] = subTypeProperty;
}
유형의 속성 목록이 생성되는 곳이며, 당신이 볼 수 있듯이, 의도적으로 상속 된 클래스에 기본 클래스에서 같은 이름의 속성을 선호 코드가있다.
왜 Json.NET에서이 작업을 수행하는지 알지 못합니다. 문제를보고하고 이유를 묻는 것이 좋습니다. 한편, 당신은 선택적으로이 문제를 방지하기 위해 IContractResolver
을 사용할 수 있습니다 : 나는 완전히 Json.NET 그것이 무엇 않는 이유를 이해하지 않기 때문에
[System.AttributeUsage(AttributeTargets.Property)]
public class JsonPreferDerivedPropertyAttribute : System.Attribute
{
}
public class PreferDerivedPropertyContractResolver : DefaultContractResolver
{
static PropertyInfo GetDerivedPropertyRecursive(Type objectType, Type stopType, PropertyInfo property)
{
var parameters = property.GetIndexParameters().Select(info => info.ParameterType).ToArray();
for (; objectType != null && objectType != stopType; objectType = objectType.BaseType)
{
var derivedProperty = objectType.GetProperty(
property.Name,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, property.PropertyType,
parameters,
null);
if (derivedProperty == null)
continue;
if (derivedProperty == property)
return derivedProperty; // No override.
if (derivedProperty.GetCustomAttribute<JsonPreferDerivedPropertyAttribute>() != null)
return derivedProperty;
}
return null;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var list = base.GetSerializableMembers(objectType);
for (int i = 0; i < list.Count; i++)
{
var property = list[i] as PropertyInfo;
if (property == null)
continue;
if (property.DeclaringType != objectType)
{
var derivedProperty = GetDerivedPropertyRecursive(objectType, property.DeclaringType, property);
if (derivedProperty == null || derivedProperty == property)
continue;
if (derivedProperty != property
&& (property.GetGetMethod(true) == null || derivedProperty.GetGetMethod(true) != null)
&& (property.GetSetMethod(true) == null || derivedProperty.GetSetMethod(true) != null))
{
list[i] = derivedProperty;
}
}
}
return list;
}
}
내가 선택적으로이 작업을 수행하는 것이 좋습니다. 위의 코드는 사용자 지정 JsonPreferDerivedPropertyAttribute
특성이 적용된 파생 클래스 속성의 기본 동작을 재정의합니다.
public class Base
{
[JsonProperty]
private string Type { get { return "Base"; } }
}
public class Inherited : Base
{
[JsonProperty]
[JsonPreferDerivedPropertyAttribute]
private string Type { get { return "Inherited"; } }
}
public class VeryInherited : Inherited
{
[JsonProperty]
public string VeryInheritedProperty { get { return "VeryInherited"; } }
}
public static class TestOverride
{
public static void Test()
{
var inherited = new Inherited();
var json1 = JsonConvert.SerializeObject(inherited, Formatting.Indented, new JsonSerializerSettings() { ContractResolver = new PreferDerivedPropertyContractResolver() });
var veryInherited = new VeryInherited();
var json2 = JsonConvert.SerializeObject(veryInherited, Formatting.Indented, new JsonSerializerSettings() { ContractResolver = new PreferDerivedPropertyContractResolver() });
Debug.WriteLine(json1);
Debug.WriteLine(json2);
}
}
그리고 출력은 다음과 같습니다 :
{
"Type": "Inherited"
}
및
{
"VeryInheritedProperty": "VeryInherited",
"Type": "Inherited"
}
출처
2015-01-11 22:12:35
dbc
는 귀하의 재산에'new' 키워드를 사용 해봤를
그리고는 좋아 사용할 수 있습니까? –
있습니다. 무시 작업 만 –
개인 속성 대신 개인 필드를 사용하십시오. 제대로 직렬화됩니다. –