Skip to content

Commit 975545a

Browse files
committed
Various improvements, and added test for discriminators.
1 parent d087b6c commit 975545a

16 files changed

+122
-50
lines changed

src/MongoDB.Bson/BsonExtensionMethods.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public static byte[] ToBson(
7777
/// </summary>
7878
/// <param name="obj"></param>
7979
/// <param name="nominalType"></param>
80-
/// <param name="domain"></param>
80+
/// <param name="serializationDomain"></param>
8181
/// <param name="writerSettings"></param>
8282
/// <param name="serializer"></param>
8383
/// <param name="configurator"></param>
@@ -89,7 +89,7 @@ public static byte[] ToBson(
8989
public static byte[] ToBson(
9090
this object obj,
9191
Type nominalType,
92-
IBsonSerializationDomain domain,
92+
IBsonSerializationDomain serializationDomain,
9393
BsonBinaryWriterSettings writerSettings = null,
9494
IBsonSerializer serializer = null,
9595
Action<BsonSerializationContext.Builder> configurator = null,
@@ -109,7 +109,7 @@ public static byte[] ToBson(
109109

110110
if (serializer == null)
111111
{
112-
serializer = domain.LookupSerializer(nominalType);
112+
serializer = serializationDomain.LookupSerializer(nominalType);
113113
}
114114
if (serializer.ValueType != nominalType)
115115
{
@@ -171,7 +171,7 @@ public static BsonDocument ToBsonDocument(
171171
/// </summary>
172172
/// <param name="obj"></param>
173173
/// <param name="nominalType"></param>
174-
/// <param name="domain"></param>
174+
/// <param name="serializationDomain"></param>
175175
/// <param name="serializer"></param>
176176
/// <param name="configurator"></param>
177177
/// <param name="args"></param>
@@ -181,7 +181,7 @@ public static BsonDocument ToBsonDocument(
181181
public static BsonDocument ToBsonDocument(
182182
this object obj,
183183
Type nominalType,
184-
IBsonSerializationDomain domain,
184+
IBsonSerializationDomain serializationDomain,
185185
IBsonSerializer serializer = null,
186186
Action<BsonSerializationContext.Builder> configurator = null,
187187
BsonSerializationArgs args = default)
@@ -211,7 +211,7 @@ public static BsonDocument ToBsonDocument(
211211
return convertibleToBsonDocument.ToBsonDocument(); // use the provided ToBsonDocument method
212212
}
213213

214-
serializer = domain.LookupSerializer(nominalType);
214+
serializer = serializationDomain.LookupSerializer(nominalType);
215215
}
216216
if (serializer.ValueType != nominalType)
217217
{

src/MongoDB.Bson/IO/IBsonReader.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public interface IBsonReader : IDisposable
6262
/// <summary>
6363
/// Pops the settings.
6464
/// </summary>
65-
void PopSettings(); //TODO Why do we have push and pop methods? They are not used
65+
void PopSettings(); //TODO Why do we have push and pop methods? They are not used. We should remove them.
6666

6767
/// <summary>
6868
/// Pushes new settings for the reader.
@@ -246,6 +246,14 @@ public interface IBsonReader : IDisposable
246246
/// <param name="bookmark">The bookmark.</param>
247247
void ReturnToBookmark(BsonReaderBookmark bookmark);
248248

249+
//TODO I'm not sure why this was not already present, there is already an equivalent in IBsonWriter.
250+
//We can also avoid adding this to the interface and casting all the occurrences of IBsonReader to BsonReader (the base class for all readers in our codebase).
251+
//Of course this would be a problem if someone implements IBsonReader in a different way.
252+
/// <summary>
253+
/// Gets the settings of the reader.
254+
/// </summary>
255+
BsonReaderSettings Settings { get; }
256+
249257
/// <summary>
250258
/// Skips the name (reader must be positioned on a name).
251259
/// </summary>

src/MongoDB.Bson/Serialization/BsonClassMap.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,7 @@ public void UnmapProperty(string propertyName)
11611161
/// Gets the discriminator convention for the class.
11621162
/// </summary>
11631163
/// <returns>The discriminator convention for the class.</returns>
1164-
internal IDiscriminatorConvention GetDiscriminatorConvention()
1164+
internal IDiscriminatorConvention GetDiscriminatorConvention(IBsonSerializationDomainInternal serializationDomain)
11651165
{
11661166
// return a cached discriminator convention when possible
11671167
var discriminatorConvention = _discriminatorConvention;
@@ -1198,7 +1198,7 @@ IDiscriminatorConvention LookupDiscriminatorConvention()
11981198
return classMap._discriminatorConvention;
11991199
}
12001200

1201-
if (BsonSerializer.IsDiscriminatorConventionRegisteredAtThisLevel(classMap._classType))
1201+
if (serializationDomain.IsDiscriminatorConventionRegisteredAtThisLevel(classMap._classType))
12021202
{
12031203
// in this case LookupDiscriminatorConvention below will find it
12041204
break;
@@ -1207,17 +1207,24 @@ IDiscriminatorConvention LookupDiscriminatorConvention()
12071207
if (classMap._isRootClass)
12081208
{
12091209
// in this case auto-register a hierarchical convention for the root class and look it up as usual below
1210-
BsonSerializer.GetOrRegisterDiscriminatorConvention(classMap._classType, StandardDiscriminatorConvention.Hierarchical);
1210+
serializationDomain.GetOrRegisterDiscriminatorConvention(classMap._classType, StandardDiscriminatorConvention.Hierarchical);
12111211
break;
12121212
}
12131213

12141214
classMap = classMap._baseClassMap;
12151215
}
12161216

1217-
return BsonSerializer.LookupDiscriminatorConvention(_classType);
1217+
return serializationDomain.LookupDiscriminatorConvention(_classType);
12181218
}
12191219
}
12201220

1221+
/// <summary>
1222+
/// Gets the discriminator convention for the class.
1223+
/// </summary>
1224+
/// <returns>The discriminator convention for the class.</returns>
1225+
internal IDiscriminatorConvention GetDiscriminatorConvention()
1226+
=> GetDiscriminatorConvention(BsonSerializer.DefaultSerializationDomain as IBsonSerializationDomainInternal);
1227+
12211228
// private methods
12221229
private void AutoMapClass(IBsonSerializationDomain serializationDomain)
12231230
{

src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace MongoDB.Bson.Serialization;
88
internal class BsonClassMapDomain : IBsonClassMapDomain
99
{
1010
// private fields
11-
private readonly IBsonSerializationDomain _serializationDomain;
11+
private readonly IBsonSerializationDomainInternal _serializationDomain;
1212
private readonly Dictionary<Type, BsonClassMap> _classMaps = new();
1313

1414
public BsonClassMapDomain(BsonSerializationDomain serializationDomain)
@@ -22,14 +22,14 @@ public BsonClassMapDomain(BsonSerializationDomain serializationDomain)
2222
/// <returns>All registered class maps.</returns>
2323
public IEnumerable<BsonClassMap> GetRegisteredClassMaps()
2424
{
25-
BsonSerializer.ConfigLock.EnterReadLock(); //TODO It would make sense to look at this after the PR by Robert is merged
25+
_serializationDomain.ConfigLock.EnterReadLock();
2626
try
2727
{
2828
return _classMaps.Values.ToList(); // return a copy for thread safety
2929
}
3030
finally
3131
{
32-
BsonSerializer.ConfigLock.ExitReadLock();
32+
_serializationDomain.ConfigLock.ExitReadLock();
3333
}
3434
}
3535

@@ -45,14 +45,14 @@ public bool IsClassMapRegistered(Type type)
4545
throw new ArgumentNullException("type");
4646
}
4747

48-
BsonSerializer.ConfigLock.EnterReadLock();
48+
_serializationDomain.ConfigLock.EnterReadLock();
4949
try
5050
{
5151
return _classMaps.ContainsKey(type);
5252
}
5353
finally
5454
{
55-
BsonSerializer.ConfigLock.ExitReadLock();
55+
_serializationDomain.ConfigLock.ExitReadLock();
5656
}
5757
}
5858

@@ -68,7 +68,7 @@ public BsonClassMap LookupClassMap(Type classType)
6868
throw new ArgumentNullException("classType");
6969
}
7070

71-
BsonSerializer.ConfigLock.EnterReadLock();
71+
_serializationDomain.ConfigLock.EnterReadLock(); //TODO Remove this lock from here...
7272
try
7373
{
7474
if (_classMaps.TryGetValue(classType, out var classMap))
@@ -81,7 +81,7 @@ public BsonClassMap LookupClassMap(Type classType)
8181
}
8282
finally
8383
{
84-
BsonSerializer.ConfigLock.ExitReadLock();
84+
_serializationDomain.ConfigLock.ExitReadLock();
8585
}
8686

8787
// automatically create a new classMap for classType and register it (unless another thread does first)
@@ -91,7 +91,7 @@ public BsonClassMap LookupClassMap(Type classType)
9191
var newClassMap = (BsonClassMap)Activator.CreateInstance(classMapType);
9292
newClassMap.AutoMap(_serializationDomain);
9393

94-
BsonSerializer.ConfigLock.EnterWriteLock();
94+
_serializationDomain.ConfigLock.EnterWriteLock();
9595
try
9696
{
9797
if (!_classMaps.TryGetValue(classType, out var classMap))
@@ -104,7 +104,7 @@ public BsonClassMap LookupClassMap(Type classType)
104104
}
105105
finally
106106
{
107-
BsonSerializer.ConfigLock.ExitWriteLock();
107+
_serializationDomain.ConfigLock.ExitWriteLock();
108108
}
109109
}
110110

@@ -142,7 +142,7 @@ public void RegisterClassMap(BsonClassMap classMap)
142142
throw new ArgumentNullException("classMap");
143143
}
144144

145-
BsonSerializer.ConfigLock.EnterWriteLock();
145+
_serializationDomain.ConfigLock.EnterWriteLock();
146146
try
147147
{
148148
// note: class maps can NOT be replaced (because derived classes refer to existing instance)
@@ -151,7 +151,7 @@ public void RegisterClassMap(BsonClassMap classMap)
151151
}
152152
finally
153153
{
154-
BsonSerializer.ConfigLock.ExitWriteLock();
154+
_serializationDomain.ConfigLock.ExitWriteLock();
155155
}
156156
}
157157

@@ -227,7 +227,7 @@ public bool TryRegisterClassMap<TClass>(Func<BsonClassMap<TClass>> classMapFacto
227227
throw new ArgumentNullException(nameof(classMapFactory));
228228
}
229229

230-
BsonSerializer.ConfigLock.EnterReadLock();
230+
_serializationDomain.ConfigLock.EnterReadLock();
231231
try
232232
{
233233
if (_classMaps.ContainsKey(typeof(TClass)))
@@ -237,10 +237,10 @@ public bool TryRegisterClassMap<TClass>(Func<BsonClassMap<TClass>> classMapFacto
237237
}
238238
finally
239239
{
240-
BsonSerializer.ConfigLock.ExitReadLock();
240+
_serializationDomain.ConfigLock.ExitReadLock();
241241
}
242242

243-
BsonSerializer.ConfigLock.EnterWriteLock();
243+
_serializationDomain.ConfigLock.EnterWriteLock();
244244
try
245245
{
246246
if (_classMaps.ContainsKey(typeof(TClass)))
@@ -257,7 +257,7 @@ public bool TryRegisterClassMap<TClass>(Func<BsonClassMap<TClass>> classMapFacto
257257
}
258258
finally
259259
{
260-
BsonSerializer.ConfigLock.ExitWriteLock();
260+
_serializationDomain.ConfigLock.ExitWriteLock();
261261
}
262262
}
263263
}

src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ private BsonDeserializationContext(
4141
_allowDuplicateElementNames = allowDuplicateElementNames;
4242
_dynamicArraySerializer = dynamicArraySerializer;
4343
_dynamicDocumentSerializer = dynamicDocumentSerializer;
44-
_serializationDomain = (reader as BsonReader)!.Settings?.SerializationDomain ?? BsonSerializer.DefaultSerializationDomain;
44+
_serializationDomain = reader.Settings?.SerializationDomain ?? BsonSerializer.DefaultSerializationDomain;
4545
}
4646

4747
// public properties

src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public abstract class BsonSerializationProviderBase : IRegistryAwareBsonSerializ
2626
/// <inheritdoc/>
2727
public virtual IBsonSerializer GetSerializer(Type type)
2828
{
29-
return GetSerializer(type, BsonSerializer.SerializerRegistry); //TODO We can keep this as is
29+
return GetSerializer(type, BsonSerializer.SerializerRegistry); //TODO We can keep this as is? I think in the long run we should remove this overload.
3030
}
3131

3232
/// <inheritdoc/>
@@ -40,7 +40,7 @@ public virtual IBsonSerializer GetSerializer(Type type)
4040
/// <returns>A serializer.</returns>
4141
protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDefinition, params Type[] typeArguments)
4242
{
43-
return CreateGenericSerializer(serializerTypeDefinition, typeArguments, BsonSerializer.SerializerRegistry); //TODO We can keep this as is
43+
return CreateGenericSerializer(serializerTypeDefinition, typeArguments, BsonSerializer.SerializerRegistry); //TODO We can keep this as is? I think in the long run we should remove this overload.
4444
}
4545

4646
/// <summary>
@@ -65,7 +65,7 @@ protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDef
6565
/// <returns>A serializer.</returns>
6666
protected virtual IBsonSerializer CreateSerializer(Type serializerType)
6767
{
68-
return CreateSerializer(serializerType, BsonSerializer.SerializerRegistry); //TODO We can keep this as is
68+
return CreateSerializer(serializerType, BsonSerializer.SerializerRegistry); //TODO We can keep this as is? I think in the long run we should remove this overload.
6969
}
7070

7171
/// <summary>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public ScalarDiscriminatorConvention(string elementName)
4343
/// <param name="actualType">The actual type.</param>
4444
/// <returns>The discriminator value.</returns>
4545
public override BsonValue GetDiscriminator(Type nominalType, Type actualType) =>
46-
GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultSerializationDomain);
46+
GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultSerializationDomain); //TODO method should not be used, remove it in the future
4747

4848
/// <inheritdoc />
4949
public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain)

src/MongoDB.Bson/Serialization/IBsonIdProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ public interface IBsonIdProvider
3636
/// //TODO
3737
/// </summary>
3838
/// <param name="document"></param>
39-
/// <param name="domain"></param>
39+
/// <param name="serializationDomain"></param>
4040
/// <param name="id"></param>
4141
/// <param name="idNominalType"></param>
4242
/// <param name="idGenerator"></param>
4343
/// <returns></returns>
44-
bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType, out IIdGenerator idGenerator);
44+
bool GetDocumentId(object document, IBsonSerializationDomain serializationDomain, out object id, out Type idNominalType, out IIdGenerator idGenerator);
4545

4646
/// <summary>
4747
/// Sets the document Id.

src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static TValue Deserialize<TValue>(this IBsonSerializer<TValue> serializer
5858
public static IDiscriminatorConvention GetDiscriminatorConvention(this IBsonSerializer serializer) =>
5959
serializer is IHasDiscriminatorConvention hasDiscriminatorConvention
6060
? hasDiscriminatorConvention.DiscriminatorConvention
61-
: BsonSerializer.LookupDiscriminatorConvention(serializer.ValueType); //TODO We can keep this as is
61+
: BsonSerializer.LookupDiscriminatorConvention(serializer.ValueType); //TODO We can keep this as is? In the long run this method should have the domain passed.
6262

6363
/// <summary>
6464
/// Serializes a value.

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public BsonClassMapSerializer(BsonClassMap classMap)
5858

5959
// public properties
6060
/// <inheritdoc/>
61-
public IDiscriminatorConvention DiscriminatorConvention => _classMap.GetDiscriminatorConvention();
61+
public IDiscriminatorConvention DiscriminatorConvention => _classMap.GetDiscriminatorConvention(); //TODO This should be removed, because we need to have the serialization domain.
6262

6363
/// <summary>
6464
/// Gets a value indicating whether this serializer's discriminator is compatible with the object serializer.
@@ -88,7 +88,7 @@ public override TClass Deserialize(BsonDeserializationContext context, BsonDeser
8888
return default(TClass);
8989
}
9090

91-
var discriminatorConvention = _classMap.GetDiscriminatorConvention();
91+
var discriminatorConvention = _classMap.GetDiscriminatorConvention(context.SerializationDomain as IBsonSerializationDomainInternal);
9292

9393
var actualType = discriminatorConvention.GetActualType(bsonReader, args.NominalType);
9494
if (actualType == typeof(TClass))
@@ -146,7 +146,7 @@ public TClass DeserializeClass(BsonDeserializationContext context)
146146
}
147147
}
148148

149-
var discriminatorConvention = _classMap.GetDiscriminatorConvention();
149+
var discriminatorConvention = _classMap.GetDiscriminatorConvention(context.SerializationDomain as IBsonSerializationDomainInternal);
150150
var allMemberMaps = _classMap.AllMemberMaps;
151151
var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex;
152152
var memberMapBitArray = FastMemberMapHelper.GetBitArray(allMemberMaps.Count);
@@ -329,7 +329,7 @@ public bool GetDocumentId(
329329
=> GetDocumentId(document, BsonSerializer.DefaultSerializationDomain, out id, out idNominalType, out idGenerator);
330330

331331
/// <inheritdoc/>
332-
public bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType,
332+
public bool GetDocumentId(object document, IBsonSerializationDomain serializationDomain, out object id, out Type idNominalType,
333333
out IIdGenerator idGenerator)
334334
{
335335
var idMemberMap = _classMap.IdMemberMap;
@@ -642,11 +642,11 @@ private void SerializeExtraElements(BsonSerializationContext context, object obj
642642

643643
private void SerializeDiscriminator(BsonSerializationContext context, Type nominalType, object obj)
644644
{
645-
var discriminatorConvention = _classMap.GetDiscriminatorConvention();
645+
var discriminatorConvention = _classMap.GetDiscriminatorConvention(context.SerializationDomain as IBsonSerializationDomainInternal);
646646
if (discriminatorConvention != null)
647647
{
648648
var actualType = obj.GetType();
649-
var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType);
649+
var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType, context.SerializationDomain);
650650
if (discriminator != null)
651651
{
652652
context.Writer.WriteName(discriminatorConvention.ElementName);

0 commit comments

Comments
 (0)