Merge branch 'MerickOWA-enumerablefix'
This commit is contained in:
@@ -614,5 +614,36 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
}
|
||||
#pragma warning restore 618
|
||||
#endif
|
||||
|
||||
public class ClassWithExtensionData
|
||||
{
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, object> Data { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtensionDataGetterCanBeIteratedMultipleTimes()
|
||||
{
|
||||
DefaultContractResolver resolver = new DefaultContractResolver();
|
||||
JsonObjectContract contract = (JsonObjectContract)resolver.ResolveContract(typeof(ClassWithExtensionData));
|
||||
|
||||
ClassWithExtensionData myClass = new ClassWithExtensionData
|
||||
{
|
||||
Data = new Dictionary<string, object>
|
||||
{
|
||||
{ "SomeField", "Field" },
|
||||
}
|
||||
};
|
||||
|
||||
ExtensionDataGetter getter = contract.ExtensionDataGetter;
|
||||
|
||||
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,49 +576,29 @@ namespace Newtonsoft.Json.Serialization
|
||||
contract.ExtensionDataValueType = valueType;
|
||||
}
|
||||
|
||||
internal struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>, IEnumerator<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 IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
|
||||
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.GetEnumerator();
|
||||
}
|
||||
|
||||
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; }
|
||||
_e = e;
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
|
||||
{
|
||||
return this;
|
||||
foreach (KeyValuePair<TEnumeratorKey, TEnumeratorValue> item in _e)
|
||||
{
|
||||
yield return new KeyValuePair<object, object>(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this;
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user