From 196d6a274b1ee6da59446855ab1946a5e5062ef5 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 6 Feb 2016 10:47:44 +1300 Subject: [PATCH] -Fixed iterating over extension data multiple times --- .../Serialization/ContractResolverTests.cs | 14 +++++++++----- .../Serialization/DefaultContractResolver.cs | 10 ++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs index 4f49e979..85b3f3ea 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs @@ -624,10 +624,10 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void ExtensionDataGetterCanBeIteratedMultipleTimes() { - var resolver = new DefaultContractResolver(); - var contract = (JsonObjectContract)resolver.ResolveContract(typeof(ClassWithExtensionData)); + DefaultContractResolver resolver = new DefaultContractResolver(); + JsonObjectContract contract = (JsonObjectContract)resolver.ResolveContract(typeof(ClassWithExtensionData)); - var myClass = new ClassWithExtensionData + ClassWithExtensionData myClass = new ClassWithExtensionData { Data = new Dictionary { @@ -635,9 +635,13 @@ namespace Newtonsoft.Json.Tests.Serialization } }; - var getter = contract.ExtensionDataGetter; + ExtensionDataGetter getter = contract.ExtensionDataGetter; - var extensionData = getter(myClass); + IEnumerable> dictionaryData = getter(myClass).ToDictionary(kv => kv.Key, kv => kv.Value); + Assert.IsTrue(dictionaryData.Any()); + Assert.IsTrue(dictionaryData.Any()); + + IEnumerable> extensionData = getter(myClass); Assert.IsTrue(extensionData.Any()); Assert.IsTrue(extensionData.Any()); // second test fails if the enumerator returned isn't reset } diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 9c5ef398..bf970338 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -555,7 +555,7 @@ namespace Newtonsoft.Json.Serialization if (extensionDataAttribute.WriteData) { - Type enumerableWrapper = typeof(DictionaryEnumerator<,>).MakeGenericType(keyType, valueType); + Type enumerableWrapper = typeof(EnumerableDictionaryWrapper<,>).MakeGenericType(keyType, valueType); ConstructorInfo constructors = enumerableWrapper.GetConstructors().First(); ObjectConstructor createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructors); @@ -576,11 +576,13 @@ namespace Newtonsoft.Json.Serialization contract.ExtensionDataValueType = valueType; } - internal struct DictionaryEnumerator : IEnumerable> + // leave as class instead of struct + // will be always return as an interface and boxed + internal class EnumerableDictionaryWrapper : IEnumerable> { private readonly IEnumerable> _e; - public DictionaryEnumerator(IEnumerable> e) + public EnumerableDictionaryWrapper(IEnumerable> e) { ValidationUtils.ArgumentNotNull(e, nameof(e)); _e = e; @@ -588,7 +590,7 @@ namespace Newtonsoft.Json.Serialization public IEnumerator> GetEnumerator() { - foreach (var item in _e) + foreach (KeyValuePair item in _e) { yield return new KeyValuePair(item.Key, item.Value); }