Skip to content

Commit 060902a

Browse files
author
rstam
committed
CSHARP-750: Optimize serialization of enumerable types.
1 parent 3ccfbb1 commit 060902a

File tree

8 files changed

+753
-806
lines changed

8 files changed

+753
-806
lines changed

MongoDB.Bson/IO/BsonBinaryWriter.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ namespace MongoDB.Bson.IO
2424
/// </summary>
2525
public class BsonBinaryWriter : BsonWriter
2626
{
27+
// private static fields
28+
private static readonly UTF8Encoding __strictUtf8Encoding = new UTF8Encoding(false, true);
29+
2730
// private fields
2831
private Stream _stream; // can be null if we're only writing to the buffer
2932
private BsonBuffer _buffer;
3033
private bool _disposeBuffer;
3134
private BsonBinaryWriterSettings _binaryWriterSettings; // same value as in base class just declared as derived class
3235
private BsonBinaryWriterContext _context;
33-
private readonly UTF8Encoding _encoding = new UTF8Encoding(false, true);
3436

3537
// constructors
3638
/// <summary>
@@ -725,7 +727,7 @@ private void WriteNameHelper()
725727
name = Name;
726728
}
727729

728-
_buffer.WriteCString(_encoding, name); // always use strict encoding for names
730+
_buffer.WriteCString(__strictUtf8Encoding, name);
729731
}
730732
}
731733
}

MongoDB.Bson/MongoDB.Bson.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@
254254
<Compile Include="Serialization\Serializers\DoubleSerializer.cs" />
255255
<Compile Include="Serialization\Serializers\DrawingSizeSerializer.cs" />
256256
<Compile Include="Serialization\Serializers\EnumerableSerializer.cs" />
257+
<Compile Include="Serialization\Serializers\EnumerableSerializerBase.cs" />
257258
<Compile Include="Serialization\Serializers\GuidSerializer.cs" />
258259
<Compile Include="Serialization\Serializers\ImageSerializer.cs" />
259260
<Compile Include="Serialization\Serializers\Int16Serializer.cs" />

MongoDB.Bson/Serialization/Serializers/ArraySerializer.cs

Lines changed: 36 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
using System;
1717
using System.Collections.Generic;
18-
using System.IO;
19-
using MongoDB.Bson.IO;
2018
using MongoDB.Bson.Serialization.Options;
2119

2220
namespace MongoDB.Bson.Serialization.Serializers
@@ -25,7 +23,7 @@ namespace MongoDB.Bson.Serialization.Serializers
2523
/// Represents a serializer for one-dimensional arrays.
2624
/// </summary>
2725
/// <typeparam name="T">The type of the elements.</typeparam>
28-
public class ArraySerializer<T> : BsonBaseSerializer, IBsonArraySerializer
26+
public class ArraySerializer<T> : EnumerableSerializerBase<T>, IBsonArraySerializer
2927
{
3028
// constructors
3129
/// <summary>
@@ -36,123 +34,56 @@ public ArraySerializer()
3634
{
3735
}
3836

39-
// public methods
37+
// protected methods
4038
/// <summary>
41-
/// Deserializes an object from a BsonReader.
39+
/// Adds the item.
4240
/// </summary>
43-
/// <param name="bsonReader">The BsonReader.</param>
44-
/// <param name="nominalType">The nominal type of the object.</param>
45-
/// <param name="actualType">The actual type of the object.</param>
46-
/// <param name="options">The serialization options.</param>
47-
/// <returns>An object.</returns>
48-
public override object Deserialize(
49-
BsonReader bsonReader,
50-
Type nominalType,
51-
Type actualType,
52-
IBsonSerializationOptions options)
41+
/// <param name="instance">The instance.</param>
42+
/// <param name="item">The item.</param>
43+
protected override void AddItem(object instance, T item)
5344
{
54-
VerifyTypes(nominalType, actualType, typeof(T[]));
55-
var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options);
56-
var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions;
57-
58-
var bsonType = bsonReader.GetCurrentBsonType();
59-
switch (bsonType)
60-
{
61-
case BsonType.Null:
62-
bsonReader.ReadNull();
63-
return null;
64-
case BsonType.Array:
65-
bsonReader.ReadStartArray();
66-
var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(T));
67-
var list = new List<T>();
68-
69-
var itemNominalType = typeof(T);
70-
var itemNominalTypeSerializer = BsonSerializer.LookupSerializer(typeof(T));
71-
72-
while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
73-
{
74-
var elementType = itemNominalType.IsValueType ? itemNominalType : discriminatorConvention.GetActualType(bsonReader, typeof(T));
75-
var serializer = itemNominalType.IsValueType ? itemNominalTypeSerializer : BsonSerializer.LookupSerializer(elementType);
76-
var element = (T)serializer.Deserialize(bsonReader, typeof(T), elementType, itemSerializationOptions);
77-
list.Add(element);
78-
}
79-
bsonReader.ReadEndArray();
80-
return list.ToArray();
81-
case BsonType.Document:
82-
bsonReader.ReadStartDocument();
83-
bsonReader.ReadString("_t"); // skip over discriminator
84-
bsonReader.ReadName("_v");
85-
var value = Deserialize(bsonReader, actualType, actualType, options);
86-
bsonReader.ReadEndDocument();
87-
return value;
88-
default:
89-
var message = string.Format("Can't deserialize a {0} from BsonType {1}.", actualType.FullName, bsonType);
90-
throw new FileFormatException(message);
91-
}
45+
((List<T>)instance).Add(item);
9246
}
9347

9448
/// <summary>
95-
/// Gets the serialization info for individual items of an enumerable type.
49+
/// Creates the instance.
9650
/// </summary>
97-
/// <returns>The serialization info for the items.</returns>
98-
public BsonSerializationInfo GetItemSerializationInfo()
51+
/// <param name="actualType">The actual type.</param>
52+
/// <returns>The instance.</returns>
53+
protected override object CreateInstance(Type actualType)
9954
{
100-
string elementName = null;
101-
var serializer = BsonSerializer.LookupSerializer(typeof(T));
102-
var nominalType = typeof(T);
103-
IBsonSerializationOptions serializationOptions = null;
104-
return new BsonSerializationInfo(elementName, serializer, nominalType, serializationOptions);
55+
return new List<T>();
10556
}
10657

10758
/// <summary>
108-
/// Serializes an object to a BsonWriter.
59+
/// Enumerates the items.
10960
/// </summary>
110-
/// <param name="bsonWriter">The BsonWriter.</param>
111-
/// <param name="nominalType">The nominal type.</param>
112-
/// <param name="value">The object.</param>
113-
/// <param name="options">The serialization options.</param>
114-
public override void Serialize(
115-
BsonWriter bsonWriter,
116-
Type nominalType,
117-
object value,
118-
IBsonSerializationOptions options)
61+
/// <param name="instance">The instance.</param>
62+
/// <returns>The items.</returns>
63+
protected override IEnumerable<T> EnumerateItemsInSerializationOrder(object instance)
11964
{
120-
if (value == null)
121-
{
122-
bsonWriter.WriteNull();
123-
}
124-
else
125-
{
126-
var actualType = value.GetType();
127-
VerifyTypes(nominalType, actualType, typeof(T[]));
128-
129-
if (nominalType == typeof(object))
130-
{
131-
bsonWriter.WriteStartDocument();
132-
bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType));
133-
bsonWriter.WriteName("_v");
134-
Serialize(bsonWriter, actualType, value, options);
135-
bsonWriter.WriteEndDocument();
136-
return;
137-
}
138-
139-
var array = (T[])value;
140-
var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options);
141-
var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions;
142-
143-
var itemNominalType = typeof(T);
144-
var itemNominalTypeSerializer = BsonSerializer.LookupSerializer(itemNominalType);
145-
146-
bsonWriter.WriteStartArray();
65+
return (IEnumerable<T>)instance;
66+
}
14767

148-
foreach (var item in array)
149-
{
150-
var itemSerializer = (itemNominalType.IsValueType || item == null) ? itemNominalTypeSerializer : BsonSerializer.LookupSerializer(item.GetType());
151-
itemSerializer.Serialize(bsonWriter, itemNominalType, item, itemSerializationOptions);
152-
}
68+
/// <summary>
69+
/// Finalizes the result.
70+
/// </summary>
71+
/// <param name="instance">The instance.</param>
72+
/// <param name="actualType">The actual type.</param>
73+
/// <returns>The result.</returns>
74+
protected override object FinalizeResult(object instance, Type actualType)
75+
{
76+
return ((List<T>)instance).ToArray();
77+
}
15378

154-
bsonWriter.WriteEndArray();
155-
}
79+
/// <summary>
80+
/// Verifies the types.
81+
/// </summary>
82+
/// <param name="nominalType">Type nominal type.</param>
83+
/// <param name="actualType">The actual type.</param>
84+
protected override void VerifyTypes(Type nominalType, Type actualType)
85+
{
86+
VerifyTypes(nominalType, actualType, typeof(T[]));
15687
}
15788
}
15889
}

0 commit comments

Comments
 (0)