Skip to content

Commit f54ba02

Browse files
committed
CSHARP-5286: Add IHierarchicalDiscriminatorConvention and IScalarDiscriminatorConvention interfaces.
1 parent 1c1e46c commit f54ba02

33 files changed

+670
-145
lines changed

src/MongoDB.Bson/Serialization/BsonClassMap.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,21 @@ public void SetDiscriminator(string discriminator)
10931093
_discriminator = discriminator;
10941094
}
10951095

1096+
/// <summary>
1097+
/// Sets the discriminator convention.
1098+
/// </summary>
1099+
/// <param name="discriminatorConvention">The discriminator convention.</param>
1100+
public void SetDiscriminatorConvention(IDiscriminatorConvention discriminatorConvention)
1101+
{
1102+
if (discriminatorConvention == null)
1103+
{
1104+
throw new ArgumentNullException("discriminatorConvention");
1105+
}
1106+
1107+
if (_frozen) { ThrowFrozenException(); }
1108+
_discriminatorConvention = discriminatorConvention;
1109+
}
1110+
10961111
/// <summary>
10971112
/// Sets whether a discriminator is required when serializing this class.
10981113
/// </summary>
@@ -1308,8 +1323,8 @@ internal IDiscriminatorConvention GetDiscriminatorConvention()
13081323
var discriminatorConvention = _discriminatorConvention;
13091324
if (discriminatorConvention == null)
13101325
{
1311-
// it's possible but harmless for multiple threads to do the initial lookup at the same time
1312-
discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(_classType);
1326+
// it's possible but harmless for multiple threads to do the field initialization at the same time
1327+
discriminatorConvention = _hasRootClass ? StandardDiscriminatorConvention.Hierarchical : StandardDiscriminatorConvention.Scalar;
13131328
_discriminatorConvention = discriminatorConvention;
13141329
}
13151330
return discriminatorConvention;

src/MongoDB.Bson/Serialization/BsonSerializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,13 +398,13 @@ public static IDiscriminatorConvention LookupDiscriminatorConvention(Type type)
398398
else
399399
{
400400
// inherit the discriminator convention from the closest parent (that isn't object) that has one
401-
// otherwise default to the standard hierarchical convention
401+
// otherwise default to the standard scalar convention
402402
Type parentType = typeInfo.BaseType;
403403
while (true)
404404
{
405405
if (parentType == typeof(object))
406406
{
407-
convention = StandardDiscriminatorConvention.Hierarchical;
407+
convention = StandardDiscriminatorConvention.Scalar;
408408
break;
409409
}
410410
if (__discriminatorConventions.TryGetValue(parentType, out convention))

src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace MongoDB.Bson.Serialization.Conventions
2222
/// <summary>
2323
/// Represents a discriminator convention where the discriminator is an array of all the discriminators provided by the class maps of the root class down to the actual type.
2424
/// </summary>
25-
public class HierarchicalDiscriminatorConvention : StandardDiscriminatorConvention
25+
public class HierarchicalDiscriminatorConvention : StandardDiscriminatorConvention, IHierarchicalDiscriminatorConvention
2626
{
2727
// constructors
2828
/// <summary>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* Copyright 2010-present MongoDB 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+
namespace MongoDB.Bson.Serialization.Conventions
17+
{
18+
/// <summary>
19+
/// Represents a discriminator convention where the discriminator for each type in a polymorphic hierarchy is an array representing the hierarchy.
20+
/// </summary>
21+
public interface IHierarchicalDiscriminatorConvention : IDiscriminatorConvention
22+
{
23+
}
24+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* Copyright 2010-present MongoDB 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+
18+
namespace MongoDB.Bson.Serialization.Conventions
19+
{
20+
/// <summary>
21+
/// Represents a discriminator convention where the discriminator for each type in a polymorphic hierarchy is a scalar.
22+
/// </summary>
23+
public interface IScalarDiscriminatorConvention : IDiscriminatorConvention
24+
{
25+
/// <summary>
26+
/// Returns the discriminators for a type and all of its known subtypes.
27+
/// </summary>
28+
/// <param name="type">The type.</param>
29+
/// <returns>The discriminators.</returns>
30+
BsonValue[] GetDiscriminatorsForTypeAndSubTypes(Type type);
31+
}
32+
}

src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,14 @@ public override BsonValue GetDiscriminator(Type nominalType, Type actualType)
4343
{
4444
// TODO: this isn't quite right, not all classes are serialized using a class map serializer
4545
var classMap = BsonClassMap.LookupClassMap(actualType);
46-
return classMap.Discriminator;
46+
if (actualType != nominalType || classMap.DiscriminatorIsRequired)
47+
{
48+
return classMap.Discriminator;
49+
}
50+
else
51+
{
52+
return null;
53+
}
4754
}
4855
}
4956
}

src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
using System;
1717
using MongoDB.Bson.IO;
18+
using MongoDB.Bson.Serialization.Conventions;
1819

1920
namespace MongoDB.Bson.Serialization
2021
{
@@ -49,6 +50,16 @@ public static TValue Deserialize<TValue>(this IBsonSerializer<TValue> serializer
4950
return serializer.Deserialize(context, args);
5051
}
5152

53+
/// <summary>
54+
/// Gets the discriminator convention for a serializer.
55+
/// </summary>
56+
/// <param name="serializer">The serializer.</param>
57+
/// <returns>The discriminator convention.</returns>
58+
public static IDiscriminatorConvention GetDiscriminatorConvention(this IBsonSerializer serializer) =>
59+
serializer is IHasDiscriminatorConvention hasDiscriminatorConvention
60+
? hasDiscriminatorConvention.DiscriminatorConvention
61+
: BsonSerializer.LookupDiscriminatorConvention(serializer.ValueType);
62+
5263
/// <summary>
5364
/// Serializes a value.
5465
/// </summary>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* Copyright 2010-present MongoDB 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 MongoDB.Bson.Serialization.Conventions;
17+
18+
namespace MongoDB.Bson.Serialization
19+
{
20+
/// <summary>
21+
/// Represents a serializer that has a DiscriminatorConvention property.
22+
/// </summary>
23+
public interface IHasDiscriminatorConvention
24+
{
25+
/// <summary>
26+
/// Gets the discriminator convention.
27+
/// </summary>
28+
IDiscriminatorConvention DiscriminatorConvention { get; }
29+
}
30+
}

src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.ComponentModel;
1919
using System.Reflection;
2020
using MongoDB.Bson.IO;
21+
using MongoDB.Bson.Serialization.Conventions;
2122
using MongoDB.Bson.Serialization.Serializers;
2223

2324
namespace MongoDB.Bson.Serialization
@@ -26,7 +27,7 @@ namespace MongoDB.Bson.Serialization
2627
/// Represents a serializer for a class map.
2728
/// </summary>
2829
/// <typeparam name="TClass">The type of the class.</typeparam>
29-
public sealed class BsonClassMapSerializer<TClass> : SerializerBase<TClass>, IBsonIdProvider, IBsonDocumentSerializer, IBsonPolymorphicSerializer
30+
public sealed class BsonClassMapSerializer<TClass> : SerializerBase<TClass>, IBsonIdProvider, IBsonDocumentSerializer, IBsonPolymorphicSerializer, IHasDiscriminatorConvention
3031
{
3132
// private fields
3233
private readonly BsonClassMap _classMap;
@@ -56,6 +57,9 @@ public BsonClassMapSerializer(BsonClassMap classMap)
5657
}
5758

5859
// public properties
60+
/// <inheritdoc/>
61+
public IDiscriminatorConvention DiscriminatorConvention => _classMap.GetDiscriminatorConvention();
62+
5963
/// <summary>
6064
/// Gets a value indicating whether this serializer's discriminator is compatible with the object serializer.
6165
/// </summary>

src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ protected virtual TValue DeserializeValue(BsonDeserializationContext context, Bs
100100
/// <returns>The actual type.</returns>
101101
protected virtual Type GetActualType(BsonDeserializationContext context)
102102
{
103-
var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(TValue));
103+
var discriminatorConvention = this.GetDiscriminatorConvention();
104104
return discriminatorConvention.GetActualType(context.Reader, typeof(TValue));
105105
}
106106

0 commit comments

Comments
 (0)