Skip to content

Commit a66b88e

Browse files
IDictionary<TKey, TValue> support (#156)
* Added failing spec * Added IDictionary<,> serialization support
1 parent f341ce1 commit a66b88e

File tree

2 files changed

+193
-8
lines changed

2 files changed

+193
-8
lines changed
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using FluentAssertions;
5+
using Xunit;
6+
7+
namespace Hyperion.Tests
8+
{
9+
public class GenericDictionarySerializerTests : TestBase
10+
{
11+
[Fact]
12+
public void CanSerializeDictionary()
13+
{
14+
var customDict = new CustomDictionary<string, int>(new Dictionary<string, int>()
15+
{
16+
["key"] = 1
17+
});
18+
SerializeAndAssertEquivalent(customDict);
19+
}
20+
21+
private void SerializeAndAssertEquivalent<T>(T expected)
22+
{
23+
Serialize(expected);
24+
Reset();
25+
var res = Deserialize<T>();
26+
res.Should().BeEquivalentTo(expected);
27+
AssertMemoryStreamConsumed();
28+
}
29+
30+
/// <summary>
31+
/// Just a custom class wrapper for another <see cref="IDictionary{TKey,TValue}"/>
32+
/// </summary>
33+
class CustomDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary
34+
{
35+
private readonly IDictionary<TKey, TValue> _dictGeneric;
36+
private readonly IDictionary _dict;
37+
38+
/// <summary>
39+
/// For serialization
40+
/// </summary>
41+
public CustomDictionary() : this(new Dictionary<TKey, TValue>())
42+
{
43+
}
44+
45+
public CustomDictionary(Dictionary<TKey, TValue> dict)
46+
{
47+
_dictGeneric = dict;
48+
_dict = dict;
49+
}
50+
51+
/// <inheritdoc />
52+
public bool Contains(object key)
53+
{
54+
return _dict.Contains(key);
55+
}
56+
57+
/// <inheritdoc />
58+
IDictionaryEnumerator IDictionary.GetEnumerator()
59+
{
60+
return _dict.GetEnumerator();
61+
}
62+
63+
/// <inheritdoc />
64+
public void Remove(object key)
65+
{
66+
_dict.Remove(key);
67+
}
68+
69+
/// <inheritdoc />
70+
public bool IsFixedSize => _dict.IsFixedSize;
71+
72+
/// <inheritdoc />
73+
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
74+
{
75+
return _dictGeneric.GetEnumerator();
76+
}
77+
78+
/// <inheritdoc />
79+
IEnumerator IEnumerable.GetEnumerator()
80+
{
81+
return ((IEnumerable) _dictGeneric).GetEnumerator();
82+
}
83+
84+
/// <inheritdoc />
85+
public void Add(KeyValuePair<TKey, TValue> item)
86+
{
87+
_dictGeneric.Add(item);
88+
}
89+
90+
/// <inheritdoc />
91+
public void Add(object key, object? value)
92+
{
93+
_dict.Add(key, value);
94+
}
95+
96+
/// <inheritdoc />
97+
public void Clear()
98+
{
99+
_dictGeneric.Clear();
100+
}
101+
102+
/// <inheritdoc />
103+
public bool Contains(KeyValuePair<TKey, TValue> item)
104+
{
105+
return _dictGeneric.Contains(item);
106+
}
107+
108+
/// <inheritdoc />
109+
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
110+
{
111+
_dictGeneric.CopyTo(array, arrayIndex);
112+
}
113+
114+
/// <inheritdoc />
115+
public bool Remove(KeyValuePair<TKey, TValue> item)
116+
{
117+
return _dictGeneric.Remove(item);
118+
}
119+
120+
/// <inheritdoc />
121+
public void CopyTo(Array array, int index)
122+
{
123+
_dict.CopyTo(array, index);
124+
}
125+
126+
/// <inheritdoc />
127+
public int Count => _dictGeneric.Count;
128+
129+
/// <inheritdoc />
130+
public bool IsSynchronized => _dict.IsSynchronized;
131+
132+
/// <inheritdoc />
133+
public object SyncRoot => _dict.SyncRoot;
134+
135+
/// <inheritdoc />
136+
public bool IsReadOnly => _dictGeneric.IsReadOnly;
137+
138+
/// <inheritdoc />
139+
public object? this[object key]
140+
{
141+
get => _dict[key];
142+
set => _dict[key] = value;
143+
}
144+
145+
/// <inheritdoc />
146+
public void Add(TKey key, TValue value)
147+
{
148+
_dictGeneric.Add(key, value);
149+
}
150+
151+
/// <inheritdoc />
152+
public bool ContainsKey(TKey key)
153+
{
154+
return _dictGeneric.ContainsKey(key);
155+
}
156+
157+
/// <inheritdoc />
158+
public bool Remove(TKey key)
159+
{
160+
return _dictGeneric.Remove(key);
161+
}
162+
163+
/// <inheritdoc />
164+
public bool TryGetValue(TKey key, out TValue value)
165+
{
166+
return _dictGeneric.TryGetValue(key, out value);
167+
}
168+
169+
/// <inheritdoc />
170+
public TValue this[TKey key]
171+
{
172+
get => _dictGeneric[key];
173+
set => _dictGeneric[key] = value;
174+
}
175+
176+
/// <inheritdoc />
177+
public ICollection<TKey> Keys => _dictGeneric.Keys;
178+
179+
/// <inheritdoc />
180+
ICollection IDictionary.Values => _dict.Values;
181+
182+
/// <inheritdoc />
183+
ICollection IDictionary.Keys => _dict.Keys;
184+
185+
/// <inheritdoc />
186+
public ICollection<TValue> Values => _dictGeneric.Values;
187+
}
188+
}
189+
}

src/Hyperion/SerializerFactories/DictionarySerializerFactory.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,18 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
4343

4444
ObjectReader reader = (stream, session) =>
4545
{
46-
throw new NotSupportedException("Generic IDictionary<TKey,TValue> are not yet supported");
47-
#pragma warning disable CS0162 // Unreachable code detected
48-
var instance = Activator.CreateInstance(type);
49-
#pragma warning restore CS0162 // Unreachable code detected
46+
var instance = Activator.CreateInstance(type) as IDictionary;
5047
if (preserveObjectReferences)
5148
{
5249
session.TrackDeserializedObject(instance);
5350
}
5451
var count = stream.ReadInt32(session);
55-
var entries = new DictionaryEntry[count];
5652
for (var i = 0; i < count; i++)
5753
{
5854
var entry = (DictionaryEntry) stream.ReadObject(session);
59-
entries[i] = entry;
55+
instance.Add(entry.Key, entry.Value);
6056
}
61-
//TODO: populate dictionary
57+
6258
return instance;
6359
};
6460

@@ -70,7 +66,7 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
7066
}
7167
var dict = obj as IDictionary;
7268
// ReSharper disable once PossibleNullReferenceException
73-
Int32Serializer.WriteValueImpl(stream,dict.Count,session);
69+
Int32Serializer.WriteValueImpl(stream, dict.Count, session);
7470
foreach (var item in dict)
7571
{
7672
stream.WriteObject(item, typeof (DictionaryEntry), elementSerializer,

0 commit comments

Comments
 (0)