Skip to content

Commit 66554a2

Browse files
authored
IGNITE-18438 .NET: Fix marshalling of nested binarizable structures with different schemas. (apache#10484)
1 parent 7d46e28 commit 66554a2

File tree

2 files changed

+96
-23
lines changed

2 files changed

+96
-23
lines changed

modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryStructureTest.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
namespace Apache.Ignite.Core.Tests.Binary
1919
{
2020
using System;
21+
using System.Collections;
2122
using System.Collections.Generic;
2223
using System.Diagnostics.CodeAnalysis;
2324
using System.IO;
@@ -211,6 +212,90 @@ public void TestMultithreadedRandomFields()
211212

212213
}, Environment.ProcessorCount, 5);
213214
}
215+
216+
/// <summary>
217+
/// Test serializing nested binarizable objects with different schemas.
218+
/// </summary>
219+
[Test]
220+
public void TestSerializeNestedStructureWithDifferentSchemas()
221+
{
222+
var marsh = new Marshaller(new BinaryConfiguration(typeof(Item)));
223+
224+
var simple = new Item(new List<string> { "f1", "f2" });
225+
var nested = new Item(new List<string> { "f3" },
226+
new List<Item> {new Item(new List<string> { "f1" })});
227+
228+
var simpleMarsh = marsh.Marshal(simple);
229+
var nestedMarsh = marsh.Marshal(nested);
230+
231+
Assert.AreEqual(new List<string> {"f1", "f2"}, marsh.Unmarshal<Item>(simpleMarsh).FieldNames);
232+
Assert.IsEmpty(marsh.Unmarshal<Item>(simpleMarsh).Children);
233+
234+
Assert.AreEqual(new List<string> { "f3" }, marsh.Unmarshal<Item>(nestedMarsh).FieldNames);
235+
Assert.AreEqual(1, marsh.Unmarshal<Item>(nestedMarsh).Children.Count);
236+
Assert.AreEqual(new List<string> { "f1" }, marsh.Unmarshal<Item>(nestedMarsh).Children[0].FieldNames);
237+
Assert.IsEmpty(marsh.Unmarshal<Item>(nestedMarsh).Children[0].Children);
238+
}
239+
}
240+
241+
/// <summary>
242+
/// A composite structure consisting of the specified fields and optional children of the same
243+
/// <see cref="Item"/> type.
244+
/// </summary>
245+
class Item : IBinarizable
246+
{
247+
private List<string> _fieldNames;
248+
private List<Item> _children;
249+
250+
public Item(List<string> fieldNames, List<Item> children)
251+
{
252+
_fieldNames = fieldNames;
253+
_children = children;
254+
}
255+
256+
public Item(List<string> fieldNames)
257+
: this(fieldNames, new List<Item>())
258+
{
259+
}
260+
261+
public List<string> FieldNames
262+
{
263+
get { return _fieldNames; }
264+
}
265+
266+
public List<Item> Children
267+
{
268+
get { return _children; }
269+
}
270+
271+
public void WriteBinary(IBinaryWriter writer)
272+
{
273+
writer.WriteCollection(nameof(_children), _children);
274+
writer.WriteCollection(nameof(_fieldNames), _fieldNames);
275+
276+
foreach (var name in _fieldNames)
277+
{
278+
writer.WriteString(name, name);
279+
}
280+
}
281+
282+
public void ReadBinary(IBinaryReader reader)
283+
{
284+
_children = (List<Item>)reader.ReadCollection(
285+
nameof(_children),
286+
size => new List<Item>(size),
287+
(collection, obj) => ((List<Item>) collection).Add((Item) obj));
288+
289+
_fieldNames = (List<string>)reader.ReadCollection(
290+
nameof(_fieldNames),
291+
size => new List<string>(size),
292+
(collection, obj) => ((List<string>) collection).Add((string) obj));
293+
294+
foreach (var name in _fieldNames)
295+
{
296+
Assert.AreEqual(name, reader.ReadString(name));
297+
}
298+
}
214299
}
215300

216301
[SuppressMessage("ReSharper", "InconsistentNaming")]

modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
1919
{
2020
using System;
2121
using System.Collections.Generic;
22-
using System.Diagnostics;
2322
using System.Diagnostics.CodeAnalysis;
2423
using System.Linq;
2524
using Apache.Ignite.Core.Binary;
@@ -34,12 +33,6 @@ internal class BinaryType : IBinaryType
3433
public static readonly BinaryType Empty =
3534
new BinaryType(BinaryTypeId.Object, BinaryTypeNames.TypeNameObject, null, null, false, null, null, null);
3635

37-
/** Empty dictionary. */
38-
private static readonly IDictionary<string, BinaryField> EmptyDict = new Dictionary<string, BinaryField>();
39-
40-
/** Empty list. */
41-
private static readonly ICollection<string> EmptyList = new List<string>().AsReadOnly();
42-
4336
/** Type name map. */
4437
private static readonly string[] TypeNames = new string[byte.MaxValue];
4538

@@ -219,7 +212,9 @@ public BinaryType(int typeId, string typeName, IDictionary<string, BinaryField>
219212
_typeId = typeId;
220213
_typeName = typeName;
221214
_affinityKeyFieldName = affKeyFieldName;
222-
_fields = fields;
215+
216+
_fields = fields ?? new Dictionary<string, BinaryField>();
217+
223218
_isEnum = isEnum;
224219
_enumNameToValue = enumValues;
225220

@@ -254,7 +249,7 @@ public string TypeName
254249
/// </summary>
255250
public ICollection<string> Fields
256251
{
257-
get { return _fields != null ? _fields.Keys : EmptyList; }
252+
get { return _fields.Keys; }
258253
}
259254

260255
/// <summary>
@@ -268,19 +263,14 @@ public string GetFieldTypeName(string fieldName)
268263
{
269264
IgniteArgumentCheck.NotNullOrEmpty(fieldName, "fieldName");
270265

271-
if (_fields != null)
272-
{
273-
BinaryField fieldMeta;
274-
275-
if (!_fields.TryGetValue(fieldName, out fieldMeta))
276-
{
277-
throw new BinaryObjectException("BinaryObject field does not exist: " + fieldName);
278-
}
266+
BinaryField fieldMeta;
279267

280-
return GetTypeName(fieldMeta.TypeId);
268+
if (!_fields.TryGetValue(fieldName, out fieldMeta))
269+
{
270+
throw new BinaryObjectException("BinaryObject field does not exist: " + fieldName);
281271
}
282-
283-
return null;
272+
273+
return GetTypeName(fieldMeta.TypeId);
284274
}
285275

286276
/// <summary>
@@ -332,7 +322,7 @@ public IBinaryTypeDescriptor Descriptor
332322
/// <returns>Fields map.</returns>
333323
public IDictionary<string, BinaryField> GetFieldsMap()
334324
{
335-
return _fields ?? EmptyDict;
325+
return _fields;
336326
}
337327

338328
/// <summary>
@@ -359,8 +349,6 @@ public void UpdateFields(IDictionary<string, BinaryField> fields)
359349
if (fields == null || fields.Count == 0)
360350
return;
361351

362-
Debug.Assert(_fields != null);
363-
364352
foreach (var field in fields)
365353
_fields[field.Key] = field.Value;
366354
}

0 commit comments

Comments
 (0)