From 621916f5a6d1f6cf234bf7baa2f23b75ee279d01 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Tue, 19 Jan 2010 08:22:35 +0000 Subject: [PATCH] -Implemented INotifyCollectionChanged on JContainer in Silverlight -Added StreamingContext to JsonSerializer -Added CreateMemberValueProvider method to DefaultContractResolver -Fixed not falling back the original class from the metadata class when attribute not found --- .../Linq/JObjectTests.cs | 39 ++++++++++++++++ .../LinqToSqlClassesSerializationTests.cs | 10 ++++- .../SerializationEventAttributeTests.cs | 32 +++++++++++++ Src/Newtonsoft.Json/JsonSerializer.cs | 14 ++++++ Src/Newtonsoft.Json/JsonSerializerSettings.cs | 10 ++++- Src/Newtonsoft.Json/Linq/JContainer.cs | 45 ++++++++++++++++++- Src/Newtonsoft.Json/Linq/JObject.cs | 4 ++ .../Serialization/DefaultContractResolver.cs | 20 ++++++--- .../DefaultSerializationBinder.cs | 27 ++++++++++- .../Serialization/JsonContract.cs | 23 +++++----- .../JsonSerializerInternalBase.cs | 2 +- .../JsonSerializerInternalReader.cs | 16 +++---- .../JsonSerializerInternalWriter.cs | 14 +++--- .../Serialization/JsonSerializerProxy.cs | 6 +++ .../Serialization/JsonTypeReflector.cs | 12 ++++- 15 files changed, 233 insertions(+), 41 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index 014c00cf..c161ea73 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Converters; using System.IO; using System.Collections; +using System.Collections.Specialized; #if !PocketPC && !SILVERLIGHT using System.Web.UI; #endif @@ -1304,6 +1305,44 @@ Parameter name: arrayIndex")] Assert.AreEqual(index, 0); Assert.AreEqual(2, (int)o["Test1"]); } +#else + [Test] + public void ListChanged() + { + JProperty p1 = new JProperty("Test1", 1); + JProperty p2 = new JProperty("Test2", "Two"); + JObject o = new JObject(p1, p2); + + NotifyCollectionChangedAction? changedType = null; + int? index = null; + + o.CollectionChanged += (s, a) => + { + changedType = a.Action; + index = a.NewStartingIndex; + }; + + JProperty p3 = new JProperty("Test3", "III"); + + o.Add(p3); + Assert.AreEqual(changedType, NotifyCollectionChangedAction.Add); + Assert.AreEqual(index, 2); + Assert.AreEqual(p3, ((IList)o)[index.Value]); + + JProperty p4 = new JProperty("Test4", "IV"); + + ((IList)o)[index.Value] = p4; + Assert.AreEqual(changedType, NotifyCollectionChangedAction.Replace); + Assert.AreEqual(index, 2); + Assert.AreEqual(p4, ((IList)o)[index.Value]); + Assert.IsFalse(((IList)o).Contains(p3)); + Assert.IsTrue(((IList)o).Contains(p4)); + + o["Test1"] = 2; + Assert.AreEqual(changedType, NotifyCollectionChangedAction.Replace); + Assert.AreEqual(index, 0); + Assert.AreEqual(2, (int)o["Test1"]); + } #endif [Test] diff --git a/Src/Newtonsoft.Json.Tests/LinqToSql/LinqToSqlClassesSerializationTests.cs b/Src/Newtonsoft.Json.Tests/LinqToSql/LinqToSqlClassesSerializationTests.cs index c2151729..6695203c 100644 --- a/Src/Newtonsoft.Json.Tests/LinqToSql/LinqToSqlClassesSerializationTests.cs +++ b/Src/Newtonsoft.Json.Tests/LinqToSql/LinqToSqlClassesSerializationTests.cs @@ -7,6 +7,8 @@ using Newtonsoft.Json.Tests.LinqToSql; using NUnit.Framework; using System.Reflection; using System.ComponentModel; +using Newtonsoft.Json.Serialization; +using System.Data.Linq.Mapping; namespace Newtonsoft.Json.Tests.LinqToSql { @@ -97,6 +99,12 @@ namespace Newtonsoft.Json.Tests.LinqToSql Assert.AreEqual(1, person.PersonRoles[0].Role.PersonRoles.Count); Assert.AreEqual("Name!", person.Department.Name); + + TableAttribute tableAttribute = JsonTypeReflector.GetAttribute(typeof(Person)); + Assert.AreEqual("", tableAttribute.Name); + + ColumnAttribute columnAttribute = JsonTypeReflector.GetAttribute(typeof(Person).GetProperty("FirstName")); + Assert.AreEqual("_FirstName", columnAttribute.Storage); } } -} +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs index f5257e0e..7c15d94d 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/SerializationEventAttributeTests.cs @@ -28,6 +28,7 @@ using System; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.Serialization; using System.Text; using Newtonsoft.Json.Tests; using Newtonsoft.Json.Tests.TestObjects; @@ -230,6 +231,37 @@ namespace Newtonsoft.Json.Tests.Serialization Console.WriteLine(obj.Member4); // This value was set after deserialization. } + +#if !SILVERLIGHT + public class SerializationEventContextTestObject + { + public string TestMember { get; set; } + + [OnSerializing] + internal void OnSerializingMethod(StreamingContext context) + { + TestMember = context.State + " " + context.Context; + } + } + + [Test] + public void SerializationEventContextTest() + { + SerializationEventContextTestObject value = new SerializationEventContextTestObject(); + + string json = JsonConvert.SerializeObject(value, Formatting.Indented, new JsonSerializerSettings + { + Context = + new StreamingContext( + StreamingContextStates.Remoting, + "ContextValue") + }); + + Assert.AreEqual(@"{ + ""TestMember"": ""Remoting ContextValue"" +}", json); + } +#endif } } #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index 58255ee5..f9435793 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -53,6 +53,7 @@ namespace Newtonsoft.Json private IContractResolver _contractResolver; private IReferenceResolver _referenceResolver; private SerializationBinder _binder; + private StreamingContext _context; /// /// Occurs when the errors during serialization and deserialization. @@ -250,6 +251,16 @@ namespace Newtonsoft.Json } set { _contractResolver = value; } } + + /// + /// Gets or sets the used by the serializer when invoking serialization callback methods. + /// + /// The context. + public virtual StreamingContext Context + { + get { return _context; } + set { _context = value; } + } #endregion /// @@ -265,6 +276,8 @@ namespace Newtonsoft.Json _preserveReferencesHandling = JsonSerializerSettings.DefaultPreserveReferencesHandling; _constructorHandling = JsonSerializerSettings.DefaultConstructorHandling; _typeNameHandling = JsonSerializerSettings.DefaultTypeNameHandling; + _context = JsonSerializerSettings.DefaultContext; + _binder = DefaultSerializationBinder.Instance; } @@ -290,6 +303,7 @@ namespace Newtonsoft.Json jsonSerializer.NullValueHandling = settings.NullValueHandling; jsonSerializer.DefaultValueHandling = settings.DefaultValueHandling; jsonSerializer.ConstructorHandling = settings.ConstructorHandling; + jsonSerializer.Context = settings.Context; if (settings.Error != null) jsonSerializer.Error += settings.Error; diff --git a/Src/Newtonsoft.Json/JsonSerializerSettings.cs b/Src/Newtonsoft.Json/JsonSerializerSettings.cs index 500ce0b8..d8532f43 100644 --- a/Src/Newtonsoft.Json/JsonSerializerSettings.cs +++ b/Src/Newtonsoft.Json/JsonSerializerSettings.cs @@ -21,6 +21,7 @@ namespace Newtonsoft.Json internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; + internal static readonly StreamingContext DefaultContext = new StreamingContext(); /// /// Gets or sets how reference loops (e.g. a class referencing itself) is handled. @@ -89,7 +90,13 @@ namespace Newtonsoft.Json /// Gets or sets the error handler called during serialization and deserialization. /// /// The error handler called during serialization and deserialization. - public EventHandler Error { get; set;} + public EventHandler Error { get; set; } + + /// + /// Gets or sets the used by the serializer when invoking serialization callback methods. + /// + /// The context. + public StreamingContext Context { get; set; } /// /// Initializes a new instance of the class. @@ -103,6 +110,7 @@ namespace Newtonsoft.Json DefaultValueHandling = DefaultDefaultValueHandling; PreserveReferencesHandling = DefaultPreserveReferencesHandling; TypeNameHandling = DefaultTypeNameHandling; + Context = DefaultContext; Converters = new List(); } } diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index ecd21917..d6f75517 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -32,6 +32,7 @@ using System.Collections; using System.Diagnostics; using System.Globalization; using System.ComponentModel; +using System.Collections.Specialized; #if !SILVERLIGHT using Newtonsoft.Json.Linq.ComponentModel; #endif @@ -45,7 +46,7 @@ namespace Newtonsoft.Json.Linq #if !SILVERLIGHT , ITypedList, IBindingList #else - , IList + , IList, INotifyCollectionChanged #endif { #if !SILVERLIGHT @@ -58,6 +59,11 @@ namespace Newtonsoft.Json.Linq /// Occurs before an item is added to the collection. /// public event AddingNewEventHandler AddingNew; +#else + /// + /// Occurs when the items list of the collection has changed, or the collection is reset. + /// + public event NotifyCollectionChangedEventHandler CollectionChanged; #endif private JToken _content; @@ -93,7 +99,7 @@ namespace Newtonsoft.Json.Linq internal void CheckReentrancy() { if (_busy) - throw new InvalidOperationException("ObservableCollection_CannotChangeObservableCollection"); + throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType())); } #if !SILVERLIGHT @@ -116,6 +122,28 @@ namespace Newtonsoft.Json.Linq { ListChangedEventHandler handler = ListChanged; + if (handler != null) + { + _busy = true; + try + { + handler(this, e); + } + finally + { + _busy = false; + } + } + } +#else + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) + { + NotifyCollectionChangedEventHandler handler = CollectionChanged; + if (handler != null) { _busy = true; @@ -281,6 +309,9 @@ namespace Newtonsoft.Json.Linq #if !SILVERLIGHT if (ListChanged != null) OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, IndexOfItem(item))); +#else + if (CollectionChanged != null) + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, IndexOfItem(item))); #endif } @@ -370,6 +401,8 @@ namespace Newtonsoft.Json.Linq #if !SILVERLIGHT OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); +#else + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, token, index)); #endif return; @@ -414,6 +447,8 @@ namespace Newtonsoft.Json.Linq #if !SILVERLIGHT OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, itemIndex)); +#else + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, itemIndex)); #endif return true; @@ -433,6 +468,8 @@ namespace Newtonsoft.Json.Linq #if !SILVERLIGHT OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); +#else + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, token, index)); #endif } @@ -459,6 +496,8 @@ namespace Newtonsoft.Json.Linq #if !SILVERLIGHT OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); +#else + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); #endif } @@ -508,6 +547,8 @@ namespace Newtonsoft.Json.Linq #if !SILVERLIGHT OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, itemIndex)); +#else + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, replacement, existing, itemIndex)); #endif } diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 0087f473..72cac7c2 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -25,6 +25,7 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.IO; @@ -51,6 +52,7 @@ namespace Newtonsoft.Json.Linq /// Occurs when a property value changes. /// public event PropertyChangedEventHandler PropertyChanged; + #if !PocketPC && !SILVERLIGHT && !NET20 /// /// Occurs when a property value is changing. @@ -120,6 +122,8 @@ namespace Newtonsoft.Json.Linq OnPropertyChanged(childProperty.Name); #if !SILVERLIGHT OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty))); +#else + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty))); #endif } diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 2503ea75..caa5f07c 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -409,6 +409,20 @@ namespace Newtonsoft.Json.Serialization return properties; } + /// + /// Creates the used by the serializer to get and set values from a member. + /// + /// The member. + /// The used by the serializer to get and set values from a member. + protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member) + { +#if !PocketPC && !SILVERLIGHT + return new DynamicValueProvider(member); +#else + return new ReflectionValueProvider(member); +#endif + } + /// /// Creates a for the given . /// @@ -419,11 +433,7 @@ namespace Newtonsoft.Json.Serialization { JsonProperty property = new JsonProperty(); property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member); -#if !PocketPC && !SILVERLIGHT - property.ValueProvider = new DynamicValueProvider(member); -#else - property.ValueProvider = new ReflectionValueProvider(member); -#endif + property.ValueProvider = CreateMemberValueProvider(member); // resolve converter for property // the class type might have a converter but the property converter takes presidence diff --git a/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs index 5f760a7b..8e102006 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs @@ -1,4 +1,29 @@ -using System; +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using System; using System.Runtime.Serialization; using System.Reflection; using System.Globalization; diff --git a/Src/Newtonsoft.Json/Serialization/JsonContract.cs b/Src/Newtonsoft.Json/Serialization/JsonContract.cs index 16399ff0..fb78f1e3 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonContract.cs @@ -59,9 +59,6 @@ namespace Newtonsoft.Json.Serialization /// The converter. public JsonConverter Converter { get; set; } - private static readonly StreamingContext SerializationStreamingContextParameter = new StreamingContext(); - private static readonly object[] SerializationEventParameterValues = new object[] { SerializationStreamingContextParameter }; - #if !PocketPC /// /// Gets or sets the method called immediately after deserialization of the object. @@ -103,42 +100,42 @@ namespace Newtonsoft.Json.Serialization /// The method called when an error is thrown during the serialization of the object. public MethodInfo OnError { get; set; } - internal void InvokeOnSerializing(object o) + internal void InvokeOnSerializing(object o, StreamingContext context) { #if !PocketPC if (OnSerializing != null) - OnSerializing.Invoke(o, SerializationEventParameterValues); + OnSerializing.Invoke(o, new object[] { context }); #endif } - internal void InvokeOnSerialized(object o) + internal void InvokeOnSerialized(object o, StreamingContext context) { #if !PocketPC if (OnSerialized != null) - OnSerialized.Invoke(o, SerializationEventParameterValues); + OnSerialized.Invoke(o, new object[] { context }); #endif } - internal void InvokeOnDeserializing(object o) + internal void InvokeOnDeserializing(object o, StreamingContext context) { #if !PocketPC if (OnDeserializing != null) - OnDeserializing.Invoke(o, SerializationEventParameterValues); + OnDeserializing.Invoke(o, new object[] { context }); #endif } - internal void InvokeOnDeserialized(object o) + internal void InvokeOnDeserialized(object o, StreamingContext context) { #if !PocketPC if (OnDeserialized != null) - OnDeserialized.Invoke(o, SerializationEventParameterValues); + OnDeserialized.Invoke(o, new object[] { context }); #endif } - internal void InvokeOnError(object o, ErrorContext errorContext) + internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext) { if (OnError != null) - OnError.Invoke(o, new object[] { SerializationStreamingContextParameter, errorContext }); + OnError.Invoke(o, new object[] { context, errorContext }); } internal JsonContract(Type underlyingType) diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs index 83f8232e..2a61f533 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs @@ -64,7 +64,7 @@ namespace Newtonsoft.Json.Serialization protected bool IsErrorHandled(object currentObject, JsonContract contract, object keyValue, Exception ex) { ErrorContext errorContext = GetErrorContext(currentObject, keyValue, ex); - contract.InvokeOnError(currentObject, errorContext); + contract.InvokeOnError(currentObject, Serializer.Context, errorContext); if (!errorContext.Handled) Serializer.OnError(new ErrorEventArgs(currentObject, errorContext)); diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index a489efa7..fca5b071 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -485,7 +485,7 @@ namespace Newtonsoft.Json.Serialization if (id != null) Serializer.ReferenceResolver.AddReference(id, dictionary.UnderlyingDictionary); - contract.InvokeOnDeserializing(dictionary.UnderlyingDictionary); + contract.InvokeOnDeserializing(dictionary.UnderlyingDictionary, Serializer.Context); int initialDepth = reader.Depth; @@ -510,7 +510,7 @@ namespace Newtonsoft.Json.Serialization } break; case JsonToken.EndObject: - contract.InvokeOnDeserialized(dictionary.UnderlyingDictionary); + contract.InvokeOnDeserialized(dictionary.UnderlyingDictionary, Serializer.Context); return dictionary.UnderlyingDictionary; default: @@ -546,7 +546,7 @@ namespace Newtonsoft.Json.Serialization if (reference != null) Serializer.ReferenceResolver.AddReference(reference, list); - contract.InvokeOnDeserializing(list); + contract.InvokeOnDeserializing(list, Serializer.Context); int initialDepth = reader.Depth; @@ -555,7 +555,7 @@ namespace Newtonsoft.Json.Serialization switch (reader.TokenType) { case JsonToken.EndArray: - contract.InvokeOnDeserialized(list); + contract.InvokeOnDeserialized(list, Serializer.Context); return wrappedList.UnderlyingCollection; case JsonToken.Comment: @@ -667,7 +667,7 @@ namespace Newtonsoft.Json.Serialization if (id != null) Serializer.ReferenceResolver.AddReference(id, createdObject); - contract.InvokeOnDeserializing(createdObject); + contract.InvokeOnDeserializing(createdObject, Serializer.Context); // go through unused values and set the newly created object's properties foreach (KeyValuePair remainingPropertyValue in remainingPropertyValues) @@ -679,13 +679,13 @@ namespace Newtonsoft.Json.Serialization property.ValueProvider.SetValue(createdObject, value); } - contract.InvokeOnDeserialized(createdObject); + contract.InvokeOnDeserialized(createdObject, Serializer.Context); return createdObject; } private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, string id) { - contract.InvokeOnDeserializing(newObject); + contract.InvokeOnDeserializing(newObject, Serializer.Context); Dictionary requiredProperties = contract.Properties.Where(m => m.Required != Required.Default).ToDictionary(m => m, m => RequiredValue.None); @@ -749,7 +749,7 @@ namespace Newtonsoft.Json.Serialization throw new JsonSerializationException("Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, requiredProperty.Key.PropertyName)); } - contract.InvokeOnDeserialized(newObject); + contract.InvokeOnDeserialized(newObject, Serializer.Context); return newObject; case JsonToken.Comment: // ignore diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 44e6d0fc..1ca0daa4 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -259,13 +259,13 @@ namespace Newtonsoft.Json.Serialization private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract) { - contract.InvokeOnSerializing(value); + contract.InvokeOnSerializing(value, Serializer.Context); string s; if (TryConvertToString(value, contract.UnderlyingType, out s)) { writer.WriteValue(s); - contract.InvokeOnSerialized(value); + contract.InvokeOnSerialized(value, Serializer.Context); return; } @@ -310,7 +310,7 @@ namespace Newtonsoft.Json.Serialization writer.WriteEndObject(); SerializeStack.RemoveAt(SerializeStack.Count - 1); - contract.InvokeOnSerialized(value); + contract.InvokeOnSerialized(value, Serializer.Context); } private void WriteTypeProperty(JsonWriter writer, Type type) @@ -355,7 +355,7 @@ namespace Newtonsoft.Json.Serialization private void SerializeList(JsonWriter writer, IList values, JsonArrayContract contract) { - contract.InvokeOnSerializing(values); + contract.InvokeOnSerializing(values, Serializer.Context); SerializeStack.Add(values); @@ -419,12 +419,12 @@ namespace Newtonsoft.Json.Serialization SerializeStack.RemoveAt(SerializeStack.Count - 1); - contract.InvokeOnSerialized(values); + contract.InvokeOnSerialized(values, Serializer.Context); } private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract) { - contract.InvokeOnSerializing(values); + contract.InvokeOnSerializing(values, Serializer.Context); SerializeStack.Add(values); writer.WriteStartObject(); @@ -478,7 +478,7 @@ namespace Newtonsoft.Json.Serialization writer.WriteEndObject(); SerializeStack.RemoveAt(SerializeStack.Count - 1); - contract.InvokeOnSerialized(values); + contract.InvokeOnSerialized(values, Serializer.Context); } private string GetPropertyName(DictionaryEntry entry) diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs index a55bd8d2..11c8672b 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs @@ -112,6 +112,12 @@ namespace Newtonsoft.Json.Serialization set { _serializer.Binder = value; } } + public override StreamingContext Context + { + get { return _serializer.Context; } + set { _serializer.Context = value; } + } + public JsonSerializerProxy(JsonSerializerInternalReader serializerReader) { ValidationUtils.ArgumentNotNull(serializerReader, "serializerReader"); diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 04882bd7..c82a9691 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -197,7 +197,11 @@ namespace Newtonsoft.Json.Serialization { Type metadataType = GetAssociatedMetadataType(type); if (metadataType != null) - return ReflectionUtils.GetAttribute(metadataType, true); + { + T attribute = ReflectionUtils.GetAttribute(metadataType, true); + if (attribute != null) + return attribute; + } return ReflectionUtils.GetAttribute(type, true); } @@ -212,7 +216,11 @@ namespace Newtonsoft.Json.Serialization BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SingleOrDefault(); if (metadataTypeMemberInfo != null) - return ReflectionUtils.GetAttribute(metadataTypeMemberInfo, true); + { + T attribute = ReflectionUtils.GetAttribute(metadataTypeMemberInfo, true); + if (attribute != null) + return attribute; + } } return ReflectionUtils.GetAttribute(memberInfo, true);