From f341ce134504d9805de6abe06cbf4c46bf7b989a Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Thu, 6 Feb 2020 15:17:28 +0000
Subject: [PATCH 1/4] Bump Microsoft.NET.Test.Sdk from 16.4.0 to 16.5.0 (#155)
---
src/common.props | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/common.props b/src/common.props
index 10118f1e..18e5c1fd 100644
--- a/src/common.props
+++ b/src/common.props
@@ -12,7 +12,7 @@ Added `ArrayList` and non-generic `IEnumerable` support.
2.4.1
- 16.4.0
+ 16.5.0
1.2.2
\ No newline at end of file
From a66b88e25c71afd9f92597ab4ba2b438e3ab69d1 Mon Sep 17 00:00:00 2001
From: Igor Fedchenko
Date: Thu, 6 Feb 2020 18:18:29 +0300
Subject: [PATCH 2/4] IDictionary support (#156)
* Added failing spec
* Added IDictionary<,> serialization support
---
.../GenericDictionarySerializerTests.cs | 189 ++++++++++++++++++
.../DictionarySerializerFactory.cs | 12 +-
2 files changed, 193 insertions(+), 8 deletions(-)
create mode 100644 src/Hyperion.Tests/GenericDictionarySerializerTests.cs
diff --git a/src/Hyperion.Tests/GenericDictionarySerializerTests.cs b/src/Hyperion.Tests/GenericDictionarySerializerTests.cs
new file mode 100644
index 00000000..5edc5468
--- /dev/null
+++ b/src/Hyperion.Tests/GenericDictionarySerializerTests.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using FluentAssertions;
+using Xunit;
+
+namespace Hyperion.Tests
+{
+ public class GenericDictionarySerializerTests : TestBase
+ {
+ [Fact]
+ public void CanSerializeDictionary()
+ {
+ var customDict = new CustomDictionary(new Dictionary()
+ {
+ ["key"] = 1
+ });
+ SerializeAndAssertEquivalent(customDict);
+ }
+
+ private void SerializeAndAssertEquivalent(T expected)
+ {
+ Serialize(expected);
+ Reset();
+ var res = Deserialize();
+ res.Should().BeEquivalentTo(expected);
+ AssertMemoryStreamConsumed();
+ }
+
+ ///
+ /// Just a custom class wrapper for another
+ ///
+ class CustomDictionary : IDictionary, IDictionary
+ {
+ private readonly IDictionary _dictGeneric;
+ private readonly IDictionary _dict;
+
+ ///
+ /// For serialization
+ ///
+ public CustomDictionary() : this(new Dictionary())
+ {
+ }
+
+ public CustomDictionary(Dictionary dict)
+ {
+ _dictGeneric = dict;
+ _dict = dict;
+ }
+
+ ///
+ public bool Contains(object key)
+ {
+ return _dict.Contains(key);
+ }
+
+ ///
+ IDictionaryEnumerator IDictionary.GetEnumerator()
+ {
+ return _dict.GetEnumerator();
+ }
+
+ ///
+ public void Remove(object key)
+ {
+ _dict.Remove(key);
+ }
+
+ ///
+ public bool IsFixedSize => _dict.IsFixedSize;
+
+ ///
+ public IEnumerator> GetEnumerator()
+ {
+ return _dictGeneric.GetEnumerator();
+ }
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable) _dictGeneric).GetEnumerator();
+ }
+
+ ///
+ public void Add(KeyValuePair item)
+ {
+ _dictGeneric.Add(item);
+ }
+
+ ///
+ public void Add(object key, object? value)
+ {
+ _dict.Add(key, value);
+ }
+
+ ///
+ public void Clear()
+ {
+ _dictGeneric.Clear();
+ }
+
+ ///
+ public bool Contains(KeyValuePair item)
+ {
+ return _dictGeneric.Contains(item);
+ }
+
+ ///
+ public void CopyTo(KeyValuePair[] array, int arrayIndex)
+ {
+ _dictGeneric.CopyTo(array, arrayIndex);
+ }
+
+ ///
+ public bool Remove(KeyValuePair item)
+ {
+ return _dictGeneric.Remove(item);
+ }
+
+ ///
+ public void CopyTo(Array array, int index)
+ {
+ _dict.CopyTo(array, index);
+ }
+
+ ///
+ public int Count => _dictGeneric.Count;
+
+ ///
+ public bool IsSynchronized => _dict.IsSynchronized;
+
+ ///
+ public object SyncRoot => _dict.SyncRoot;
+
+ ///
+ public bool IsReadOnly => _dictGeneric.IsReadOnly;
+
+ ///
+ public object? this[object key]
+ {
+ get => _dict[key];
+ set => _dict[key] = value;
+ }
+
+ ///
+ public void Add(TKey key, TValue value)
+ {
+ _dictGeneric.Add(key, value);
+ }
+
+ ///
+ public bool ContainsKey(TKey key)
+ {
+ return _dictGeneric.ContainsKey(key);
+ }
+
+ ///
+ public bool Remove(TKey key)
+ {
+ return _dictGeneric.Remove(key);
+ }
+
+ ///
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ return _dictGeneric.TryGetValue(key, out value);
+ }
+
+ ///
+ public TValue this[TKey key]
+ {
+ get => _dictGeneric[key];
+ set => _dictGeneric[key] = value;
+ }
+
+ ///
+ public ICollection Keys => _dictGeneric.Keys;
+
+ ///
+ ICollection IDictionary.Values => _dict.Values;
+
+ ///
+ ICollection IDictionary.Keys => _dict.Keys;
+
+ ///
+ public ICollection Values => _dictGeneric.Values;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs b/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs
index 62bf47e0..6dbab34e 100644
--- a/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs
+++ b/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs
@@ -43,22 +43,18 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
ObjectReader reader = (stream, session) =>
{
- throw new NotSupportedException("Generic IDictionary are not yet supported");
-#pragma warning disable CS0162 // Unreachable code detected
- var instance = Activator.CreateInstance(type);
-#pragma warning restore CS0162 // Unreachable code detected
+ var instance = Activator.CreateInstance(type) as IDictionary;
if (preserveObjectReferences)
{
session.TrackDeserializedObject(instance);
}
var count = stream.ReadInt32(session);
- var entries = new DictionaryEntry[count];
for (var i = 0; i < count; i++)
{
var entry = (DictionaryEntry) stream.ReadObject(session);
- entries[i] = entry;
+ instance.Add(entry.Key, entry.Value);
}
- //TODO: populate dictionary
+
return instance;
};
@@ -70,7 +66,7 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
}
var dict = obj as IDictionary;
// ReSharper disable once PossibleNullReferenceException
- Int32Serializer.WriteValueImpl(stream,dict.Count,session);
+ Int32Serializer.WriteValueImpl(stream, dict.Count, session);
foreach (var item in dict)
{
stream.WriteObject(item, typeof (DictionaryEntry), elementSerializer,
From 01ed0c81d37ea19a210048ff262c788f2bdc2d63 Mon Sep 17 00:00:00 2001
From: Igor Fedchenko
Date: Fri, 7 Feb 2020 21:39:52 +0300
Subject: [PATCH 3/4] Update IDictionary serializer to not use
IDictionary assumption (#158)
* Updated spec to serialize object without IDictionary
* Updated implementation to not use IDictionary assumption
---
.../GenericDictionarySerializerTests.cs | 56 +------------------
.../DictionarySerializerFactory.cs | 49 +++++++++++++---
2 files changed, 41 insertions(+), 64 deletions(-)
diff --git a/src/Hyperion.Tests/GenericDictionarySerializerTests.cs b/src/Hyperion.Tests/GenericDictionarySerializerTests.cs
index 5edc5468..8bea41b7 100644
--- a/src/Hyperion.Tests/GenericDictionarySerializerTests.cs
+++ b/src/Hyperion.Tests/GenericDictionarySerializerTests.cs
@@ -30,10 +30,9 @@ private void SerializeAndAssertEquivalent(T expected)
///
/// Just a custom class wrapper for another
///
- class CustomDictionary : IDictionary, IDictionary
+ class CustomDictionary : IDictionary
{
private readonly IDictionary _dictGeneric;
- private readonly IDictionary _dict;
///
/// For serialization
@@ -45,30 +44,8 @@ public CustomDictionary() : this(new Dictionary())
public CustomDictionary(Dictionary dict)
{
_dictGeneric = dict;
- _dict = dict;
}
- ///
- public bool Contains(object key)
- {
- return _dict.Contains(key);
- }
-
- ///
- IDictionaryEnumerator IDictionary.GetEnumerator()
- {
- return _dict.GetEnumerator();
- }
-
- ///
- public void Remove(object key)
- {
- _dict.Remove(key);
- }
-
- ///
- public bool IsFixedSize => _dict.IsFixedSize;
-
///
public IEnumerator> GetEnumerator()
{
@@ -87,12 +64,6 @@ public void Add(KeyValuePair item)
_dictGeneric.Add(item);
}
- ///
- public void Add(object key, object? value)
- {
- _dict.Add(key, value);
- }
-
///
public void Clear()
{
@@ -117,31 +88,12 @@ public bool Remove(KeyValuePair item)
return _dictGeneric.Remove(item);
}
- ///
- public void CopyTo(Array array, int index)
- {
- _dict.CopyTo(array, index);
- }
-
///
public int Count => _dictGeneric.Count;
- ///
- public bool IsSynchronized => _dict.IsSynchronized;
-
- ///
- public object SyncRoot => _dict.SyncRoot;
-
///
public bool IsReadOnly => _dictGeneric.IsReadOnly;
- ///
- public object? this[object key]
- {
- get => _dict[key];
- set => _dict[key] = value;
- }
-
///
public void Add(TKey key, TValue value)
{
@@ -176,12 +128,6 @@ public TValue this[TKey key]
///
public ICollection Keys => _dictGeneric.Keys;
- ///
- ICollection IDictionary.Values => _dict.Values;
-
- ///
- ICollection IDictionary.Keys => _dict.Keys;
-
///
public ICollection Values => _dictGeneric.Values;
}
diff --git a/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs b/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs
index 6dbab34e..3e44faec 100644
--- a/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs
+++ b/src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs
@@ -39,11 +39,12 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
var preserveObjectReferences = serializer.Options.PreserveObjectReferences;
var ser = new ObjectSerializer(type);
typeMapping.TryAdd(type, ser);
- var elementSerializer = serializer.GetSerializerByType(typeof (DictionaryEntry));
+ var dictionaryTypes = GetKeyValuePairType(type);
+ var elementSerializer = serializer.GetSerializerByType(dictionaryTypes.KeyValuePairType);
ObjectReader reader = (stream, session) =>
{
- var instance = Activator.CreateInstance(type) as IDictionary;
+ var instance = Activator.CreateInstance(type); // IDictionary
if (preserveObjectReferences)
{
session.TrackDeserializedObject(instance);
@@ -51,8 +52,16 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
var count = stream.ReadInt32(session);
for (var i = 0; i < count; i++)
{
- var entry = (DictionaryEntry) stream.ReadObject(session);
- instance.Add(entry.Key, entry.Value);
+ var entry = stream.ReadObject(session); // KeyValuePair
+
+ // Get entry.Key and entry.Value
+ var key = dictionaryTypes.KeyValuePairType.GetProperty(nameof(KeyValuePair