From c1cafd078d00c9da96f5510105ccb0ee269a5f53 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Mon, 4 Jul 2011 09:16:23 +0000 Subject: [PATCH] -Added serialization constructors to all Exceptions -Added support for serialization event attributes on base classes -Changed WriteEndObject, WriteEndArray, WriteEndConstructor on JsonWriter to be virtual --- .../Properties/AssemblyInfo.cs | 2 +- .../SerializationEventAttributeTests.cs | 26 ++++++++ Src/Newtonsoft.Json/JsonReaderException.cs | 15 +++++ .../JsonSerializationException.cs | 17 +++++- Src/Newtonsoft.Json/JsonWriter.cs | 8 +-- Src/Newtonsoft.Json/JsonWriterException.cs | 17 +++++- .../Properties/AssemblyInfo.cs | 2 +- .../Schema/JsonSchemaException.cs | 15 +++++ .../Serialization/DefaultContractResolver.cs | 60 +++++++++++++++---- 9 files changed, 141 insertions(+), 21 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 95dd4f83..800165e5 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -41,5 +41,5 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: [assembly: AssemblyVersion("4.0.2.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.0.2.13825")] +[assembly: AssemblyFileVersion("4.0.2.13904")] #endif diff --git a/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs index 1041002c..ed50d151 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs @@ -232,6 +232,32 @@ namespace Newtonsoft.Json.Tests.Serialization // This value was set after deserialization. } + public class SerializationEventBaseTestObject + { + public string TestMember { get; set; } + + [OnSerializing] + internal void OnSerializingMethod(StreamingContext context) + { + TestMember = "Set!"; + } + } + + public class SerializationEventContextSubClassTestObject : SerializationEventBaseTestObject + { + } + + [Test] + public void SerializationEventContextTestObjectSubClassTest() + { + SerializationEventContextSubClassTestObject obj = new SerializationEventContextSubClassTestObject(); + + string json = JsonConvert.SerializeObject(obj, Formatting.Indented); + Assert.AreEqual(@"{ + ""TestMember"": ""Set!"" +}", json); + } + #if !SILVERLIGHT public class SerializationEventContextTestObject { diff --git a/Src/Newtonsoft.Json/JsonReaderException.cs b/Src/Newtonsoft.Json/JsonReaderException.cs index 5c3159bb..4ea4a8df 100644 --- a/Src/Newtonsoft.Json/JsonReaderException.cs +++ b/Src/Newtonsoft.Json/JsonReaderException.cs @@ -24,6 +24,7 @@ #endregion using System; +using System.Runtime.Serialization; namespace Newtonsoft.Json { @@ -76,6 +77,20 @@ namespace Newtonsoft.Json { } +#if !(WINDOWS_PHONE || SILVERLIGHT) + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// The parameter is null. + /// The class name is null or is zero (0). + public JsonReaderException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } +#endif + internal JsonReaderException(string message, Exception innerException, int lineNumber, int linePosition) : base(message, innerException) { diff --git a/Src/Newtonsoft.Json/JsonSerializationException.cs b/Src/Newtonsoft.Json/JsonSerializationException.cs index 687f4617..25d3a33a 100644 --- a/Src/Newtonsoft.Json/JsonSerializationException.cs +++ b/Src/Newtonsoft.Json/JsonSerializationException.cs @@ -25,6 +25,7 @@ using System; using System.Collections.Generic; +using System.Runtime.Serialization; using System.Text; namespace Newtonsoft.Json @@ -64,5 +65,19 @@ namespace Newtonsoft.Json : base(message, innerException) { } + +#if !(WINDOWS_PHONE || SILVERLIGHT) + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// The parameter is null. + /// The class name is null or is zero (0). + public JsonSerializationException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } +#endif } -} +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index 864d99af..9a5b8c1e 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -246,7 +246,7 @@ namespace Newtonsoft.Json /// /// Writes the end of a Json object. /// - public void WriteEndObject() + public virtual void WriteEndObject() { AutoCompleteClose(JsonToken.EndObject); } @@ -263,7 +263,7 @@ namespace Newtonsoft.Json /// /// Writes the end of an array. /// - public void WriteEndArray() + public virtual void WriteEndArray() { AutoCompleteClose(JsonToken.EndArray); } @@ -281,7 +281,7 @@ namespace Newtonsoft.Json /// /// Writes the end constructor. /// - public void WriteEndConstructor() + public virtual void WriteEndConstructor() { AutoCompleteClose(JsonToken.EndConstructor); } @@ -298,7 +298,7 @@ namespace Newtonsoft.Json /// /// Writes the end of the current Json object or array. /// - public void WriteEnd() + public virtual void WriteEnd() { WriteEnd(Peek()); } diff --git a/Src/Newtonsoft.Json/JsonWriterException.cs b/Src/Newtonsoft.Json/JsonWriterException.cs index f08e84c1..70c57ebb 100644 --- a/Src/Newtonsoft.Json/JsonWriterException.cs +++ b/Src/Newtonsoft.Json/JsonWriterException.cs @@ -25,6 +25,7 @@ using System; using System.Collections.Generic; +using System.Runtime.Serialization; using System.Text; namespace Newtonsoft.Json @@ -64,5 +65,19 @@ namespace Newtonsoft.Json : base(message, innerException) { } + +#if !(WINDOWS_PHONE || SILVERLIGHT) + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// The parameter is null. + /// The class name is null or is zero (0). + public JsonWriterException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } +#endif } -} +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index ad76c2d5..ced2ade6 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -110,7 +110,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.0.2.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.0.2.13825")] +[assembly: AssemblyFileVersion("4.0.2.13904")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs index b9f296c7..86d29243 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs @@ -24,6 +24,7 @@ #endregion using System; +using System.Runtime.Serialization; namespace Newtonsoft.Json.Schema { @@ -76,6 +77,20 @@ namespace Newtonsoft.Json.Schema { } + #if !(WINDOWS_PHONE || SILVERLIGHT) + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + /// The parameter is null. + /// The class name is null or is zero (0). + public JsonSchemaException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } +#endif + internal JsonSchemaException(string message, Exception innerException, int lineNumber, int linePosition) : base(message, innerException) { diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 8078c046..f05edcd1 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -440,7 +440,43 @@ namespace Newtonsoft.Json.Serialization ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null); } - foreach (MethodInfo method in contract.UnderlyingType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + ResolveCallbackMethods(contract, contract.UnderlyingType); + } + + private void ResolveCallbackMethods(JsonContract contract, Type t) + { + if (t.BaseType != null) + ResolveCallbackMethods(contract, t.BaseType); + + MethodInfo onSerializing; + MethodInfo onSerialized; + MethodInfo onDeserializing; + MethodInfo onDeserialized; + MethodInfo onError; + + GetCallbackMethodsForType(t, out onSerializing, out onSerialized, out onDeserializing, out onDeserialized, out onError); + + if (onSerializing != null) + contract.OnSerializing = onSerializing; + if (onSerialized != null) + contract.OnSerialized = onSerialized; + if (onDeserializing != null) + contract.OnDeserializing = onDeserializing; + if (onDeserialized != null) + contract.OnDeserialized = onDeserialized; + if (onError != null) + contract.OnError = onError; + } + + private void GetCallbackMethodsForType(Type type, out MethodInfo onSerializing, out MethodInfo onSerialized, out MethodInfo onDeserializing, out MethodInfo onDeserialized, out MethodInfo onError) + { + onSerializing = null; + onSerialized = null; + onDeserializing = null; + onDeserialized = null; + onError = null; + + foreach (MethodInfo method in type.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 @@ -450,27 +486,25 @@ namespace Newtonsoft.Json.Serialization Type prevAttributeType = null; ParameterInfo[] parameters = method.GetParameters(); -#if !PocketPC - if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), contract.OnSerializing, ref prevAttributeType)) + if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), onSerializing, ref prevAttributeType)) { - contract.OnSerializing = method; + onSerializing = method; } - if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), contract.OnSerialized, ref prevAttributeType)) + if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), onSerialized, ref prevAttributeType)) { - contract.OnSerialized = method; + onSerialized = method; } - if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), contract.OnDeserializing, ref prevAttributeType)) + if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), onDeserializing, ref prevAttributeType)) { - contract.OnDeserializing = method; + onDeserializing = method; } - if (IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), contract.OnDeserialized, ref prevAttributeType)) + if (IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), onDeserialized, ref prevAttributeType)) { - contract.OnDeserialized = method; + onDeserialized = method; } -#endif - if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), contract.OnError, ref prevAttributeType)) + if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), onError, ref prevAttributeType)) { - contract.OnError = method; + onError = method; } } }