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:
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user