diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index e52245f8..49e03762 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -597,39 +597,80 @@ namespace Newtonsoft.Json.Serialization onDeserialized = null; onError = null; - foreach (MethodInfo method in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + foreach (Type baseType in GetClassHierarchyForType(type)) { - // compact framework errors when getting parameters for a generic method - // lame, but generic methods should not be callbacks anyway - if (method.ContainsGenericParameters) - continue; + // while we allow more than one OnSerialized total, only one can be defined + // per class + MethodInfo currentOnSerializing = null; + MethodInfo currentOnSerialized = null; + MethodInfo currentOnDeserializing = null; + MethodInfo currentOnDeserialized = null; + MethodInfo currentOnError = null; - Type prevAttributeType = null; - ParameterInfo[] parameters = method.GetParameters(); + foreach (MethodInfo method in baseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + { + // compact framework errors when getting parameters for a generic method + // lame, but generic methods should not be callbacks anyway + if (method.ContainsGenericParameters) + continue; - if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), onSerializing, ref prevAttributeType)) - { - onSerializing = method; - } - if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), onSerialized, ref prevAttributeType)) - { - onSerialized = method; - } - if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), onDeserializing, ref prevAttributeType)) - { - onDeserializing = method; - } - if (IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), onDeserialized, ref prevAttributeType)) - { - onDeserialized = method; - } - if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), onError, ref prevAttributeType)) - { - onError = method; + Type prevAttributeType = null; + ParameterInfo[] parameters = method.GetParameters(); + + if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), currentOnSerializing, ref prevAttributeType)) + { + onSerializing = onSerializing ?? new List(); + onSerializing.Add(method); + currentOnSerializing = method; + } + if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), currentOnSerialized, ref prevAttributeType)) + { + onSerialized = onSerialized ?? new List(); + onSerialized.Add(method); + currentOnSerialized = method; + } + if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), currentOnDeserializing, ref prevAttributeType)) + { + onDeserializing = onDeserializing ?? new List(); + onDeserializing.Add(method); + currentOnDeserializing = method; + } + if (IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), currentOnDeserialized, ref prevAttributeType)) + { + onDeserialized = onDeserialized ?? new List(); + onDeserialized.Add(method); + currentOnDeserialized = method; + } + if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), currentOnError, ref prevAttributeType)) + { + onError = onError ?? new List(); + onError.Add(method); + currentOnError = method; + } } } } + private List GetClassHierarchyForType(Type type) + { + List ret = new List(); + + Type current = type; + while (current != null && current != typeof(object)) + { + ret.Add(current); +#if NETFX_CORE + current = current.BaseType(); +#else + current = current.BaseType; +#endif + } + + // Return the class list in order of simple => complex + ret.Reverse(); + return ret; + } + /// /// Creates a for the given type. /// @@ -1108,4 +1149,4 @@ namespace Newtonsoft.Json.Serialization return ResolvePropertyName(propertyName); } } -} \ No newline at end of file +}