Fixed an issue where iterating extensionDataGetter's enumerable multiple times or using LINQ statement on it caused inconsistant data to be returned.

This commit is contained in:
Lowell Smith
2016-02-05 15:05:42 -05:00
parent b26bccc4f6
commit 29567c5b5d
2 changed files with 35 additions and 30 deletions
@@ -614,5 +614,32 @@ namespace Newtonsoft.Json.Tests.Serialization
} }
#pragma warning restore 618 #pragma warning restore 618
#endif #endif
public class ClassWithExtensionData
{
[JsonExtensionData]
public IDictionary<string, object> Data { get; set; }
}
[Test]
public void ExtensionDataGetterCanBeIteratedMultipleTimes()
{
var resolver = new DefaultContractResolver();
var contract = (JsonObjectContract)resolver.ResolveContract(typeof(ClassWithExtensionData));
var myClass = new ClassWithExtensionData
{
Data = new Dictionary<string, object>
{
{ "SomeField", "Field" },
}
};
var getter = contract.ExtensionDataGetter;
var extensionData = getter(myClass);
Assert.IsTrue(extensionData.Any());
Assert.IsTrue(extensionData.Any()); // second test fails if the enumerator returned isn't reset
}
} }
} }
@@ -576,49 +576,27 @@ namespace Newtonsoft.Json.Serialization
contract.ExtensionDataValueType = valueType; contract.ExtensionDataValueType = valueType;
} }
internal struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>, IEnumerator<KeyValuePair<object, object>> internal struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>
{ {
private readonly IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e; private readonly IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
public DictionaryEnumerator(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e) public DictionaryEnumerator(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
{ {
ValidationUtils.ArgumentNotNull(e, nameof(e)); ValidationUtils.ArgumentNotNull(e, nameof(e));
_e = e.GetEnumerator(); _e = e;
}
public bool MoveNext()
{
return _e.MoveNext();
}
public void Reset()
{
_e.Reset();
}
public KeyValuePair<object, object> Current
{
get { return new KeyValuePair<object, object>(_e.Current.Key, _e.Current.Value); }
}
public void Dispose()
{
_e.Dispose();
}
object IEnumerator.Current
{
get { return Current; }
} }
public IEnumerator<KeyValuePair<object, object>> GetEnumerator() public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
{ {
return this; foreach (var item in _e)
{
yield return new KeyValuePair<object, object>(item.Key, item.Value);
}
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return this; return GetEnumerator();
} }
} }