-Fixed iterating over extension data multiple times

This commit is contained in:
James Newton-King
2016-02-06 10:47:44 +13:00
parent 29567c5b5d
commit 196d6a274b
2 changed files with 15 additions and 9 deletions
@@ -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<string, object>
{
@@ -635,9 +635,13 @@ namespace Newtonsoft.Json.Tests.Serialization
}
};
var getter = contract.ExtensionDataGetter;
ExtensionDataGetter getter = contract.ExtensionDataGetter;
var extensionData = getter(myClass);
IEnumerable<KeyValuePair<object, object>> dictionaryData = getter(myClass).ToDictionary(kv => kv.Key, kv => kv.Value);
Assert.IsTrue(dictionaryData.Any());
Assert.IsTrue(dictionaryData.Any());
IEnumerable<KeyValuePair<object, object>> extensionData = getter(myClass);
Assert.IsTrue(extensionData.Any());
Assert.IsTrue(extensionData.Any()); // second test fails if the enumerator returned isn't reset
}
@@ -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<object> createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructors);
@@ -576,11 +576,13 @@ namespace Newtonsoft.Json.Serialization
contract.ExtensionDataValueType = valueType;
}
internal struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>
// leave as class instead of struct
// will be always return as an interface and boxed
internal class EnumerableDictionaryWrapper<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>
{
private readonly IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
public DictionaryEnumerator(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
public EnumerableDictionaryWrapper(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
{
ValidationUtils.ArgumentNotNull(e, nameof(e));
_e = e;
@@ -588,7 +590,7 @@ namespace Newtonsoft.Json.Serialization
public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
{
foreach (var item in _e)
foreach (KeyValuePair<TEnumeratorKey, TEnumeratorValue> item in _e)
{
yield return new KeyValuePair<object, object>(item.Key, item.Value);
}