Skip to content

Commit 147d512

Browse files
author
rstam
committed
Initial implementation of CSHARP-284 and CSHARP-308. Added IsItemOptions named parameter to BsonSerializationOptionsAttribute base class to indicate whether an attribute is intended for the items of a collection instead of for the collection itself. The problem with the current implementation using the new ItemSerializationOptionsWrapper class is that you can have attributes for the collection or for the items but not both.
1 parent 77ac96b commit 147d512

14 files changed

+486
-108
lines changed

Bson/Bson.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
<Compile Include="Serialization\Conventions\ExtraElementsMemberConventions.cs" />
100100
<Compile Include="Serialization\Conventions\IgnoreIfDefaultConventions.cs" />
101101
<Compile Include="Serialization\Conventions\SerializationOptionsConventions.cs" />
102+
<Compile Include="Serialization\Options\ItemSerializationOptionsWrapper.cs" />
102103
<Compile Include="Serialization\Options\DateTimeSerializationOptions.cs" />
103104
<Compile Include="Serialization\Options\DictionarySerializationOptions.cs" />
104105
<Compile Include="Serialization\Options\DocumentSerializationOptions.cs" />

Bson/BsonUtils.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
using MongoDB.Bson.IO;
2323
using MongoDB.Bson.Serialization;
24+
using System.Text.RegularExpressions;
2425

2526
namespace MongoDB.Bson
2627
{
@@ -32,6 +33,28 @@ public static class BsonUtils
3233
{
3334

3435
// public static methods
36+
/// <summary>
37+
/// Gets a friendly class name suitable for use in error messages.
38+
/// </summary>
39+
/// <param name="type">The type.</param>
40+
/// <returns>A friendly class name.</returns>
41+
public static string GetFriendlyTypeName(Type type)
42+
{
43+
if (!type.IsGenericType)
44+
{
45+
return type.Name;
46+
}
47+
48+
var sb = new StringBuilder();
49+
sb.AppendFormat("{0}<", Regex.Replace(type.Name, @"\`\d+$", ""));
50+
foreach (var typeParameter in type.GetGenericArguments())
51+
{
52+
sb.AppendFormat("{0}, ", GetFriendlyTypeName(typeParameter));
53+
}
54+
sb.Remove(sb.Length - 2, 2);
55+
sb.Append(">");
56+
return sb.ToString();
57+
}
3558

3659
/// <summary>
3760
/// Parses a hex string into its equivalent byte array.

Bson/Serialization/Attributes/BsonDateTimeOptionsAttribute.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,16 @@ public BsonType Representation
7777
/// <returns>The serialization options.</returns>
7878
public override IBsonSerializationOptions GetOptions()
7979
{
80+
IBsonSerializationOptions serializationOptions;
8081
if (_dateOnly)
8182
{
82-
return new DateTimeSerializationOptions(_dateOnly, _representation);
83+
serializationOptions = new DateTimeSerializationOptions(_dateOnly, _representation);
8384
}
8485
else
8586
{
86-
return new DateTimeSerializationOptions(_kind, _representation);
87+
serializationOptions = new DateTimeSerializationOptions(_kind, _representation);
8788
}
89+
return CheckIfIsItemsOptions(serializationOptions);
8890
}
8991
}
9092
}

Bson/Serialization/Attributes/BsonDictionaryOptionsAttribute.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ public DictionaryRepresentation Representation
6666
/// <returns>The serialization options.</returns>
6767
public override IBsonSerializationOptions GetOptions()
6868
{
69-
return new DictionarySerializationOptions(_representation);
69+
var serializationOptions = new DictionarySerializationOptions(_representation);
70+
return CheckIfIsItemsOptions(serializationOptions);
7071
}
7172
}
7273
}

Bson/Serialization/Attributes/BsonRepresentationAttribute.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ public bool AllowTruncation
7878
/// <returns>The serialization options.</returns>
7979
public override IBsonSerializationOptions GetOptions()
8080
{
81-
return new RepresentationSerializationOptions(_representation, _allowOverflow, _allowTruncation);
81+
var serializationOptions = new RepresentationSerializationOptions(_representation, _allowOverflow, _allowTruncation);
82+
return CheckIfIsItemsOptions(serializationOptions);
8283
}
8384
}
8485
}

Bson/Serialization/Attributes/BsonSerializationOptionsAttribute.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System.Text;
2020

2121
using MongoDB.Bson.Serialization;
22+
using MongoDB.Bson.Serialization.Options;
2223

2324
namespace MongoDB.Bson.Serialization.Attributes
2425
{
@@ -28,6 +29,8 @@ namespace MongoDB.Bson.Serialization.Attributes
2829
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
2930
public abstract class BsonSerializationOptionsAttribute : Attribute
3031
{
32+
// private fields
33+
private bool _isItemOptions;
3134
// constructors
3235
/// <summary>
3336
/// Initializes a new instance of the BsonSerializationOptionsAttribute class.
@@ -36,11 +39,39 @@ protected BsonSerializationOptionsAttribute()
3639
{
3740
}
3841

42+
// public properties
43+
/// <summary>
44+
/// Gets or sets whether this attribute should be applied to the items of the collection rather than the collection itself.
45+
/// </summary>
46+
public bool IsItemOptions
47+
{
48+
get { return _isItemOptions; }
49+
set { _isItemOptions = value; }
50+
}
51+
3952
// public methods
4053
/// <summary>
4154
/// Gets the serialization options specified by this attribute.
4255
/// </summary>
4356
/// <returns>The serialization options.</returns>
4457
public abstract IBsonSerializationOptions GetOptions();
58+
59+
// protected methods
60+
/// <summary>
61+
/// Wraps the serialization options in an ItemSerializationOptionsWrapper if IsItemOptions is true.
62+
/// </summary>
63+
/// <param name="serializationOptions">The serialization options.</param>
64+
/// <returns>The serialization options wrapped in an ItemSerializationOptionsWrapper if IsItemOptions is true; otherwise, the original serialization options.</returns>
65+
protected IBsonSerializationOptions CheckIfIsItemsOptions(IBsonSerializationOptions serializationOptions)
66+
{
67+
if (_isItemOptions)
68+
{
69+
return new ItemSerializationOptionsWrapper(serializationOptions);
70+
}
71+
else
72+
{
73+
return serializationOptions;
74+
}
75+
}
4576
}
4677
}

Bson/Serialization/Options/DictionarySerializationOptions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public class DictionarySerializationOptions : IBsonSerializationOptions
5656

5757
// private fields
5858
private DictionaryRepresentation _representation = DictionaryRepresentation.Dynamic;
59+
private IBsonSerializationOptions _itemSerializationOptions;
5960

6061
// constructors
6162
/// <summary>
@@ -125,5 +126,14 @@ public DictionaryRepresentation Representation
125126
{
126127
get { return _representation; }
127128
}
129+
130+
/// <summary>
131+
/// Gets or sets the serialization options for the items in the dictionary.
132+
/// </summary>
133+
public IBsonSerializationOptions ItemSerializationOptions
134+
{
135+
get { return _itemSerializationOptions; }
136+
set { _itemSerializationOptions = value; }
137+
}
128138
}
129139
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Copyright 2010-2012 10gen Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Linq;
19+
using System.Text;
20+
21+
namespace MongoDB.Bson.Serialization.Options
22+
{
23+
/// <summary>
24+
/// Represents serialization options for items in a collection.
25+
/// </summary>
26+
public class ItemSerializationOptionsWrapper : IBsonSerializationOptions
27+
{
28+
// private fields
29+
private IBsonSerializationOptions _serializationOptions;
30+
31+
// constructors
32+
/// <summary>
33+
/// Initializes a new instance of the ItemSerializationOptionsWrapper class.
34+
/// </summary>
35+
public ItemSerializationOptionsWrapper()
36+
{
37+
}
38+
39+
/// <summary>
40+
/// Initializes a new instance of the ItemSerializationOptionsWrapper class.
41+
/// </summary>
42+
/// <param name="itemSerializationOptions">The serialization options for items in the collection.</param>
43+
public ItemSerializationOptionsWrapper(IBsonSerializationOptions itemSerializationOptions)
44+
{
45+
_serializationOptions = itemSerializationOptions;
46+
}
47+
48+
49+
/// <summary>
50+
/// Gets or sets the serialization options for the items in the collection.
51+
/// </summary>
52+
public IBsonSerializationOptions SerializationOptions
53+
{
54+
get { return _serializationOptions; }
55+
set { _serializationOptions = value; }
56+
}
57+
}
58+
}

Bson/Serialization/Serializers/ArraySerializer.cs

Lines changed: 72 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
using MongoDB.Bson.IO;
2424
using MongoDB.Bson.Serialization;
25+
using MongoDB.Bson.Serialization.Options;
2526

2627
namespace MongoDB.Bson.Serialization.Serializers
2728
{
@@ -120,24 +121,31 @@ public override void Serialize(
120121
var actualType = value.GetType();
121122
VerifyTypes(nominalType, actualType, typeof(T[]));
122123

123-
if (nominalType != typeof(object))
124-
{
125-
bsonWriter.WriteStartArray();
126-
var array = (T[])value;
127-
for (int index = 0; index < array.Length; index++)
128-
{
129-
BsonSerializer.Serialize(bsonWriter, typeof(T), array[index]);
130-
}
131-
bsonWriter.WriteEndArray();
132-
}
133-
else
124+
if (nominalType == typeof(object))
134125
{
135126
bsonWriter.WriteStartDocument();
136127
bsonWriter.WriteString("_t", BsonClassMap.GetTypeNameDiscriminator(actualType));
137128
bsonWriter.WriteName("_v");
138129
Serialize(bsonWriter, actualType, value, options);
139130
bsonWriter.WriteEndDocument();
131+
return;
140132
}
133+
134+
IBsonSerializationOptions itemSerializationOptions = null;
135+
var itemSerializationOptionsWrapper = options as ItemSerializationOptionsWrapper;
136+
if (itemSerializationOptionsWrapper != null)
137+
{
138+
itemSerializationOptions = itemSerializationOptionsWrapper.SerializationOptions;
139+
}
140+
141+
var array = (T[])value;
142+
143+
bsonWriter.WriteStartArray();
144+
for (int index = 0; index < array.Length; index++)
145+
{
146+
BsonSerializer.Serialize(bsonWriter, typeof(T), array[index], itemSerializationOptions);
147+
}
148+
bsonWriter.WriteEndArray();
141149
}
142150
}
143151
}
@@ -250,31 +258,38 @@ public override void Serialize(
250258
var actualType = value.GetType();
251259
VerifyTypes(nominalType, actualType, typeof(T[,]));
252260

253-
if (nominalType != typeof(object))
254-
{
255-
bsonWriter.WriteStartArray();
256-
var array = (T[,])value;
257-
var length1 = array.GetLength(0);
258-
var length2 = array.GetLength(1);
259-
for (int i = 0; i < length1; i++)
260-
{
261-
bsonWriter.WriteStartArray();
262-
for (int j = 0; j < length2; j++)
263-
{
264-
BsonSerializer.Serialize(bsonWriter, typeof(T), array[i, j]);
265-
}
266-
bsonWriter.WriteEndArray();
267-
}
268-
bsonWriter.WriteEndArray();
269-
}
270-
else
261+
if (nominalType == typeof(object))
271262
{
272263
bsonWriter.WriteStartDocument();
273264
bsonWriter.WriteString("_t", BsonClassMap.GetTypeNameDiscriminator(actualType));
274265
bsonWriter.WriteName("_v");
275266
Serialize(bsonWriter, actualType, value, options);
276267
bsonWriter.WriteEndDocument();
268+
return;
269+
}
270+
271+
IBsonSerializationOptions itemSerializationOptions = null;
272+
var itemSerializationOptionsWrapper = options as ItemSerializationOptionsWrapper;
273+
if (itemSerializationOptionsWrapper != null)
274+
{
275+
itemSerializationOptions = itemSerializationOptionsWrapper.SerializationOptions;
276+
}
277+
278+
var array = (T[,])value;
279+
var length1 = array.GetLength(0);
280+
var length2 = array.GetLength(1);
281+
282+
bsonWriter.WriteStartArray();
283+
for (int i = 0; i < length1; i++)
284+
{
285+
bsonWriter.WriteStartArray();
286+
for (int j = 0; j < length2; j++)
287+
{
288+
BsonSerializer.Serialize(bsonWriter, typeof(T), array[i, j], itemSerializationOptions);
289+
}
290+
bsonWriter.WriteEndArray();
277291
}
292+
bsonWriter.WriteEndArray();
278293
}
279294
}
280295
}
@@ -404,37 +419,44 @@ public override void Serialize(
404419
var actualType = value.GetType();
405420
VerifyTypes(nominalType, actualType, typeof(T[, ,]));
406421

407-
if (nominalType != typeof(object))
422+
if (nominalType == typeof(object))
423+
{
424+
bsonWriter.WriteStartDocument();
425+
bsonWriter.WriteString("_t", BsonClassMap.GetTypeNameDiscriminator(actualType));
426+
bsonWriter.WriteName("_v");
427+
Serialize(bsonWriter, actualType, value, options);
428+
bsonWriter.WriteEndDocument();
429+
return;
430+
}
431+
432+
IBsonSerializationOptions itemSerializationOptions = null;
433+
var itemSerializationOptionsWrapper = options as ItemSerializationOptionsWrapper;
434+
if (itemSerializationOptionsWrapper != null)
435+
{
436+
itemSerializationOptions = itemSerializationOptionsWrapper.SerializationOptions;
437+
}
438+
439+
var array = (T[, ,])value;
440+
var length1 = array.GetLength(0);
441+
var length2 = array.GetLength(1);
442+
var length3 = array.GetLength(2);
443+
444+
bsonWriter.WriteStartArray();
445+
for (int i = 0; i < length1; i++)
408446
{
409447
bsonWriter.WriteStartArray();
410-
var array = (T[, ,])value;
411-
var length1 = array.GetLength(0);
412-
var length2 = array.GetLength(1);
413-
var length3 = array.GetLength(2);
414-
for (int i = 0; i < length1; i++)
448+
for (int j = 0; j < length2; j++)
415449
{
416450
bsonWriter.WriteStartArray();
417-
for (int j = 0; j < length2; j++)
451+
for (int k = 0; k < length3; k++)
418452
{
419-
bsonWriter.WriteStartArray();
420-
for (int k = 0; k < length3; k++)
421-
{
422-
BsonSerializer.Serialize(bsonWriter, typeof(T), array[i, j, k]);
423-
}
424-
bsonWriter.WriteEndArray();
453+
BsonSerializer.Serialize(bsonWriter, typeof(T), array[i, j, k], itemSerializationOptions);
425454
}
426455
bsonWriter.WriteEndArray();
427456
}
428457
bsonWriter.WriteEndArray();
429458
}
430-
else
431-
{
432-
bsonWriter.WriteStartDocument();
433-
bsonWriter.WriteString("_t", BsonClassMap.GetTypeNameDiscriminator(actualType));
434-
bsonWriter.WriteName("_v");
435-
Serialize(bsonWriter, actualType, value, options);
436-
bsonWriter.WriteEndDocument();
437-
}
459+
bsonWriter.WriteEndArray();
438460
}
439461
}
440462
}

0 commit comments

Comments
 (0)