JsonPropertyAttribute忽略派生类中的私有属性
在序列化具有私有属性的派生对象时,我遇到了Json.Net的问题。 好吧
public class Base { [JsonProperty] private string Type { get { return "Base"; } } } public class Inherited : Base { [JsonProperty] private string Type { get { return "Inherited"; } } }
当我序列化Inherited
实例时, Type
属性始终设置为“Base”。 我发现工作的唯一方法是属性受保护或公共,并在子类中重写。
为什么这样工作? 那是一个错误吗?
看起来这是Json.NET的预期行为。 来自ReflectionUtils.cs :
private static void GetChildPrivateProperties(IList 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; }
这是生成类型的属性列表的位置,正如您所看到的,有些代码有意将基类中具有相同名称的属性添加到inheritance的类中。
我不知道为什么Json.NET这样做,你可能想报告一个问题并问为什么。 在此期间,您可以使用IContractResolver
有选择地阻止此行为:
[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() != null) return derivedProperty; } return null; } protected override List 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; } }
我建议有选择地这样做,因为我不完全理解为什么Json.NET会做它的function。 上面的代码仅覆盖应用了自定义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" }
和
上述就是C#学习教程:JsonPropertyAttribute忽略派生类中的私有属性分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
{ "VeryInheritedProperty": "VeryInherited", "Type": "Inherited" }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/955162.html