From 5a93d57f2f974461ba3b57bb8c204a7df7735386 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:20:46 +0100 Subject: [PATCH 01/49] First test --- src/MongoDB.Driver/MongoClient.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/MongoDB.Driver/MongoClient.cs b/src/MongoDB.Driver/MongoClient.cs index 0fa1b4eb8d2..37c12a583dd 100644 --- a/src/MongoDB.Driver/MongoClient.cs +++ b/src/MongoDB.Driver/MongoClient.cs @@ -45,13 +45,14 @@ public sealed class MongoClient : IMongoClient private readonly IOperationExecutor _operationExecutor; private readonly MongoClientSettings _settings; private readonly ILogger _logger; + private readonly IBsonSerializerRegistry _serializerRegistry; // constructors /// /// Initializes a new instance of the MongoClient class. /// - public MongoClient() - : this(new MongoClientSettings()) + public MongoClient(IBsonSerializerRegistry serializerRegistry = null) + : this(new MongoClientSettings(), serializerRegistry) { } @@ -59,8 +60,10 @@ public MongoClient() /// Initializes a new instance of the MongoClient class. /// /// The settings. - public MongoClient(MongoClientSettings settings) + /// //TODO + public MongoClient(MongoClientSettings settings, IBsonSerializerRegistry serializerRegistry = null) { + _serializerRegistry = serializerRegistry ?? BsonSerializer.SerializerRegistry; _settings = Ensure.IsNotNull(settings, nameof(settings)).FrozenCopy(); _logger = _settings.LoggingSettings?.CreateLogger(); @@ -83,8 +86,9 @@ public MongoClient(MongoClientSettings settings) /// Initializes a new instance of the MongoClient class. /// /// The URL. - public MongoClient(MongoUrl url) - : this(MongoClientSettings.FromUrl(url)) + /// //TODO + public MongoClient(MongoUrl url, IBsonSerializerRegistry serializerRegistry = null) + : this(MongoClientSettings.FromUrl(url), serializerRegistry) { } @@ -92,12 +96,13 @@ public MongoClient(MongoUrl url) /// Initializes a new instance of the MongoClient class. /// /// The connection string. - public MongoClient(string connectionString) + /// //TODO + public MongoClient(string connectionString, IBsonSerializerRegistry serializerRegistry = null) : this(MongoClientSettings.FromConnectionString(connectionString)) { } - internal MongoClient(IOperationExecutor operationExecutor, MongoClientSettings settings) + internal MongoClient(IOperationExecutor operationExecutor, MongoClientSettings settings) //TODO Do we need to add it here too..? : this(settings) { _operationExecutor = operationExecutor; From bc33071a15f669a8873fc0ba246d4921e0dafd54 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:41:49 +0100 Subject: [PATCH 02/49] Revert "First test" This reverts commit 5a93d57f2f974461ba3b57bb8c204a7df7735386. --- src/MongoDB.Driver/MongoClient.cs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/MongoDB.Driver/MongoClient.cs b/src/MongoDB.Driver/MongoClient.cs index 37c12a583dd..0fa1b4eb8d2 100644 --- a/src/MongoDB.Driver/MongoClient.cs +++ b/src/MongoDB.Driver/MongoClient.cs @@ -45,14 +45,13 @@ public sealed class MongoClient : IMongoClient private readonly IOperationExecutor _operationExecutor; private readonly MongoClientSettings _settings; private readonly ILogger _logger; - private readonly IBsonSerializerRegistry _serializerRegistry; // constructors /// /// Initializes a new instance of the MongoClient class. /// - public MongoClient(IBsonSerializerRegistry serializerRegistry = null) - : this(new MongoClientSettings(), serializerRegistry) + public MongoClient() + : this(new MongoClientSettings()) { } @@ -60,10 +59,8 @@ public MongoClient(IBsonSerializerRegistry serializerRegistry = null) /// Initializes a new instance of the MongoClient class. /// /// The settings. - /// //TODO - public MongoClient(MongoClientSettings settings, IBsonSerializerRegistry serializerRegistry = null) + public MongoClient(MongoClientSettings settings) { - _serializerRegistry = serializerRegistry ?? BsonSerializer.SerializerRegistry; _settings = Ensure.IsNotNull(settings, nameof(settings)).FrozenCopy(); _logger = _settings.LoggingSettings?.CreateLogger(); @@ -86,9 +83,8 @@ public MongoClient(MongoClientSettings settings, IBsonSerializerRegistry seriali /// Initializes a new instance of the MongoClient class. /// /// The URL. - /// //TODO - public MongoClient(MongoUrl url, IBsonSerializerRegistry serializerRegistry = null) - : this(MongoClientSettings.FromUrl(url), serializerRegistry) + public MongoClient(MongoUrl url) + : this(MongoClientSettings.FromUrl(url)) { } @@ -96,13 +92,12 @@ public MongoClient(MongoUrl url, IBsonSerializerRegistry serializerRegistry = nu /// Initializes a new instance of the MongoClient class. /// /// The connection string. - /// //TODO - public MongoClient(string connectionString, IBsonSerializerRegistry serializerRegistry = null) + public MongoClient(string connectionString) : this(MongoClientSettings.FromConnectionString(connectionString)) { } - internal MongoClient(IOperationExecutor operationExecutor, MongoClientSettings settings) //TODO Do we need to add it here too..? + internal MongoClient(IOperationExecutor operationExecutor, MongoClientSettings settings) : this(settings) { _operationExecutor = operationExecutor; From 5e94e627149406fc9a7eae580a118c73601a9692 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:58:02 +0100 Subject: [PATCH 03/49] Added manager --- .../Serialization/BsonSerializerManager.cs | 815 ++++++++++++++++++ 1 file changed, 815 insertions(+) create mode 100644 src/MongoDB.Bson/Serialization/BsonSerializerManager.cs diff --git a/src/MongoDB.Bson/Serialization/BsonSerializerManager.cs b/src/MongoDB.Bson/Serialization/BsonSerializerManager.cs new file mode 100644 index 00000000000..cd4ea765e70 --- /dev/null +++ b/src/MongoDB.Bson/Serialization/BsonSerializerManager.cs @@ -0,0 +1,815 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Bson.Serialization.Conventions; +using MongoDB.Bson.Serialization.IdGenerators; + +namespace MongoDB.Bson.Serialization +{ + /// + /// A class that represents the BSON serialization functionality. + /// + public class BsonSerializerManager + { + // private fields + private ReaderWriterLockSlim __configLock = + new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + + private Dictionary __idGenerators = new Dictionary(); + + private Dictionary __discriminatorConventions = + new Dictionary(); + + private Dictionary> __discriminators = + new Dictionary>(); + + private HashSet __discriminatedTypes = new HashSet(); + private BsonSerializerRegistry __serializerRegistry; + + private TypeMappingSerializationProvider __typeMappingSerializationProvider; + + // ConcurrentDictionary is being used as a concurrent set of Type. The values will always be null. + private ConcurrentDictionary __typesWithRegisteredKnownTypes = + new ConcurrentDictionary(); + + private bool __useNullIdChecker = false; + private bool __useZeroIdChecker = false; + + // constructor + BsonSerializerManager() + { + CreateSerializerRegistry(); + RegisterIdGenerators(); + } + + // public properties + /// + /// Gets the serializer registry. + /// + public IBsonSerializerRegistry SerializerRegistry + { + get { return __serializerRegistry; } + } + + /// + /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// + public bool UseNullIdChecker + { + get { return __useNullIdChecker; } + set { __useNullIdChecker = value; } + } + + /// + /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// + public bool UseZeroIdChecker + { + get { return __useZeroIdChecker; } + set { __useZeroIdChecker = value; } + } + + // internal properties + internal ReaderWriterLockSlim ConfigLock + { + get { return __configLock; } + } + + // public methods + /// + /// Deserializes an object from a BsonDocument. + /// + /// The nominal type of the object. + /// The BsonDocument. + /// The configurator. + /// A deserialized value. + public TNominalType Deserialize(BsonDocument document, + Action configurator = null) + { + using (var bsonReader = new BsonDocumentReader(document)) + { + return Deserialize(bsonReader, configurator); + } + } + + /// + /// Deserializes a value. + /// + /// The nominal type of the object. + /// The BsonReader. + /// The configurator. + /// A deserialized value. + public TNominalType Deserialize(IBsonReader bsonReader, + Action configurator = null) + { + var serializer = LookupSerializer(); + var context = BsonDeserializationContext.CreateRoot(bsonReader, configurator); + return serializer.Deserialize(context); + } + + /// + /// Deserializes an object from a BSON byte array. + /// + /// The nominal type of the object. + /// The BSON byte array. + /// The configurator. + /// A deserialized value. + public TNominalType Deserialize(byte[] bytes, + Action configurator = null) + { + using (var buffer = new ByteArrayBuffer(bytes, isReadOnly: true)) + using (var stream = new ByteBufferStream(buffer)) + { + return Deserialize(stream, configurator); + } + } + + /// + /// Deserializes an object from a BSON Stream. + /// + /// The nominal type of the object. + /// The BSON Stream. + /// The configurator. + /// A deserialized value. + public TNominalType Deserialize(Stream stream, + Action configurator = null) + { + using (var bsonReader = new BsonBinaryReader(stream)) + { + return Deserialize(bsonReader, configurator); + } + } + + /// + /// Deserializes an object from a JSON string. + /// + /// The nominal type of the object. + /// The JSON string. + /// The configurator. + /// A deserialized value. + public TNominalType Deserialize(string json, + Action configurator = null) + { + using (var bsonReader = new JsonReader(json)) + { + return Deserialize(bsonReader, configurator); + } + } + + /// + /// Deserializes an object from a JSON TextReader. + /// + /// The nominal type of the object. + /// The JSON TextReader. + /// The configurator. + /// A deserialized value. + public TNominalType Deserialize(TextReader textReader, + Action configurator = null) + { + using (var bsonReader = new JsonReader(textReader)) + { + return Deserialize(bsonReader, configurator); + } + } + + /// + /// Deserializes an object from a BsonDocument. + /// + /// The BsonDocument. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + public object Deserialize(BsonDocument document, Type nominalType, + Action configurator = null) + { + using (var bsonReader = new BsonDocumentReader(document)) + { + return Deserialize(bsonReader, nominalType, configurator); + } + } + + /// + /// Deserializes a value. + /// + /// The BsonReader. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + public object Deserialize(IBsonReader bsonReader, Type nominalType, + Action configurator = null) + { + var serializer = LookupSerializer(nominalType); + var context = BsonDeserializationContext.CreateRoot(bsonReader, configurator); + return serializer.Deserialize(context); + } + + /// + /// Deserializes an object from a BSON byte array. + /// + /// The BSON byte array. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + public object Deserialize(byte[] bytes, Type nominalType, + Action configurator = null) + { + using (var buffer = new ByteArrayBuffer(bytes, isReadOnly: true)) + using (var stream = new ByteBufferStream(buffer)) + { + return Deserialize(stream, nominalType, configurator); + } + } + + /// + /// Deserializes an object from a BSON Stream. + /// + /// The BSON Stream. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + public object Deserialize(Stream stream, Type nominalType, + Action configurator = null) + { + using (var bsonReader = new BsonBinaryReader(stream)) + { + return Deserialize(bsonReader, nominalType, configurator); + } + } + + /// + /// Deserializes an object from a JSON string. + /// + /// The JSON string. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + public object Deserialize(string json, Type nominalType, + Action configurator = null) + { + using (var bsonReader = new JsonReader(json)) + { + return Deserialize(bsonReader, nominalType, configurator); + } + } + + /// + /// Deserializes an object from a JSON TextReader. + /// + /// The JSON TextReader. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + public object Deserialize(TextReader textReader, Type nominalType, + Action configurator = null) + { + using (var bsonReader = new JsonReader(textReader)) + { + return Deserialize(bsonReader, nominalType, configurator); + } + } + + internal IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, + IDiscriminatorConvention discriminatorConvention) + { + __configLock.EnterReadLock(); + try + { + if (__discriminatorConventions.TryGetValue(type, out var registeredDiscriminatorConvention)) + { + return registeredDiscriminatorConvention; + } + } + finally + { + __configLock.ExitReadLock(); + } + + __configLock.EnterWriteLock(); + try + { + if (__discriminatorConventions.TryGetValue(type, out var registeredDiscrimantorConvention)) + { + return registeredDiscrimantorConvention; + } + + RegisterDiscriminatorConvention(type, discriminatorConvention); + return discriminatorConvention; + } + finally + { + __configLock.ExitWriteLock(); + } + } + + internal bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) + { + __configLock.EnterReadLock(); + try + { + return __discriminatorConventions.ContainsKey(type); + } + finally + { + __configLock.ExitReadLock(); + } + } + + /// + /// Returns whether the given type has any discriminators registered for any of its subclasses. + /// + /// A Type. + /// True if the type is discriminated. + public bool IsTypeDiscriminated(Type type) + { + var typeInfo = type.GetTypeInfo(); + return typeInfo.IsInterface || __discriminatedTypes.Contains(type); + } + + /// + /// Looks up the actual type of an object to be deserialized. + /// + /// The nominal type of the object. + /// The discriminator. + /// The actual type of the object. + public Type LookupActualType(Type nominalType, BsonValue discriminator) + { + if (discriminator == null) + { + return nominalType; + } + + // note: EnsureKnownTypesAreRegistered handles its own locking so call from outside any lock + EnsureKnownTypesAreRegistered(nominalType); + + __configLock.EnterReadLock(); + try + { + Type actualType = null; + + HashSet hashSet; + var nominalTypeInfo = nominalType.GetTypeInfo(); + if (__discriminators.TryGetValue(discriminator, out hashSet)) + { + foreach (var type in hashSet) + { + if (nominalTypeInfo.IsAssignableFrom(type)) + { + if (actualType == null) + { + actualType = type; + } + else + { + string message = string.Format("Ambiguous discriminator '{0}'.", discriminator); + throw new BsonSerializationException(message); + } + } + } + + // no need for additional checks, we found the right type + if (actualType != null) + { + return actualType; + } + } + + if (discriminator.IsString) + { + actualType = TypeNameDiscriminator.GetActualType(discriminator.AsString); // see if it's a Type name + } + + if (actualType == null) + { + string message = string.Format("Unknown discriminator value '{0}'.", discriminator); + throw new BsonSerializationException(message); + } + + if (!nominalTypeInfo.IsAssignableFrom(actualType)) + { + string message = string.Format( + "Actual type {0} is not assignable to expected type {1}.", + actualType.FullName, nominalType.FullName); + throw new BsonSerializationException(message); + } + + return actualType; + } + finally + { + __configLock.ExitReadLock(); + } + } + + /// + /// Looks up the discriminator convention for a type. + /// + /// The type. + /// A discriminator convention. + public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) + { + __configLock.EnterReadLock(); + try + { + IDiscriminatorConvention convention; + if (__discriminatorConventions.TryGetValue(type, out convention)) + { + return convention; + } + } + finally + { + __configLock.ExitReadLock(); + } + + __configLock.EnterWriteLock(); + try + { + IDiscriminatorConvention convention; + if (!__discriminatorConventions.TryGetValue(type, out convention)) + { + var typeInfo = type.GetTypeInfo(); + if (type == typeof(object)) + { + // if there is no convention registered for object register the default one + convention = new ObjectDiscriminatorConvention("_t"); + RegisterDiscriminatorConvention(typeof(object), convention); + } + else if (typeInfo.IsInterface) + { + // TODO: should convention for interfaces be inherited from parent interfaces? + convention = LookupDiscriminatorConvention(typeof(object)); + RegisterDiscriminatorConvention(type, convention); + } + else + { + // inherit the discriminator convention from the closest parent (that isn't object) that has one + // otherwise default to the standard scalar convention + Type parentType = typeInfo.BaseType; + while (true) + { + if (parentType == typeof(object)) + { + convention = StandardDiscriminatorConvention.Scalar; + break; + } + + if (__discriminatorConventions.TryGetValue(parentType, out convention)) + { + break; + } + + parentType = parentType.GetTypeInfo().BaseType; + } + + // register this convention for all types between this and the parent type where we found the convention + var unregisteredType = type; + while (unregisteredType != parentType) + { + RegisterDiscriminatorConvention(unregisteredType, convention); + unregisteredType = unregisteredType.GetTypeInfo().BaseType; + } + } + } + + return convention; + } + finally + { + __configLock.ExitWriteLock(); + } + } + + /// + /// Looks up an IdGenerator. + /// + /// The Id type. + /// An IdGenerator for the Id type. + public IIdGenerator LookupIdGenerator(Type type) + { + __configLock.EnterReadLock(); + try + { + IIdGenerator idGenerator; + if (__idGenerators.TryGetValue(type, out idGenerator)) + { + return idGenerator; + } + } + finally + { + __configLock.ExitReadLock(); + } + + __configLock.EnterWriteLock(); + try + { + IIdGenerator idGenerator; + if (!__idGenerators.TryGetValue(type, out idGenerator)) + { + var typeInfo = type.GetTypeInfo(); + if (typeInfo.IsValueType && __useZeroIdChecker) + { + var iEquatableDefinition = typeof(IEquatable<>); + var iEquatableType = iEquatableDefinition.MakeGenericType(type); + if (iEquatableType.GetTypeInfo().IsAssignableFrom(type)) + { + var zeroIdCheckerDefinition = typeof(ZeroIdChecker<>); + var zeroIdCheckerType = zeroIdCheckerDefinition.MakeGenericType(type); + idGenerator = (IIdGenerator)Activator.CreateInstance(zeroIdCheckerType); + } + } + else if (__useNullIdChecker) + { + idGenerator = NullIdChecker.Instance; + } + else + { + idGenerator = null; + } + + __idGenerators[type] = idGenerator; // remember it even if it's null + } + + return idGenerator; + } + finally + { + __configLock.ExitWriteLock(); + } + } + + /// + /// Looks up a serializer for a Type. + /// + /// The type. + /// A serializer for type T. + public IBsonSerializer LookupSerializer() + { + return (IBsonSerializer)LookupSerializer(typeof(T)); + } + + /// + /// Looks up a serializer for a Type. + /// + /// The Type. + /// A serializer for the Type. + public IBsonSerializer LookupSerializer(Type type) + { + return __serializerRegistry.GetSerializer(type); + } + + /// + /// Registers the discriminator for a type. + /// + /// The type. + /// The discriminator. + public void RegisterDiscriminator(Type type, BsonValue discriminator) + { + var typeInfo = type.GetTypeInfo(); + if (typeInfo.IsInterface) + { + var message = string.Format("Discriminators can only be registered for classes, not for interface {0}.", + type.FullName); + throw new BsonSerializationException(message); + } + + __configLock.EnterWriteLock(); + try + { + HashSet hashSet; + if (!__discriminators.TryGetValue(discriminator, out hashSet)) + { + hashSet = new HashSet(); + __discriminators.Add(discriminator, hashSet); + } + + if (!hashSet.Contains(type)) + { + hashSet.Add(type); + + // mark all base types as discriminated (so we know that it's worth reading a discriminator) + for (var baseType = typeInfo.BaseType; baseType != null; baseType = baseType.GetTypeInfo().BaseType) + { + __discriminatedTypes.Add(baseType); + } + } + } + finally + { + __configLock.ExitWriteLock(); + } + } + + /// + /// Registers the discriminator convention for a type. + /// + /// Type type. + /// The discriminator convention. + public void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention) + { + __configLock.EnterWriteLock(); + try + { + if (!__discriminatorConventions.ContainsKey(type)) + { + __discriminatorConventions.Add(type, convention); + } + else + { + var message = string.Format("There is already a discriminator convention registered for type {0}.", + type.FullName); + throw new BsonSerializationException(message); + } + } + finally + { + __configLock.ExitWriteLock(); + } + } + + /// + /// Registers a generic serializer definition for a generic type. + /// + /// The generic type. + /// The generic serializer definition. + public void RegisterGenericSerializerDefinition( + Type genericTypeDefinition, + Type genericSerializerDefinition) + { + __typeMappingSerializationProvider.RegisterMapping(genericTypeDefinition, genericSerializerDefinition); + } + + /// + /// Registers an IdGenerator for an Id Type. + /// + /// The Id Type. + /// The IdGenerator for the Id Type. + public void RegisterIdGenerator(Type type, IIdGenerator idGenerator) + { + __configLock.EnterWriteLock(); + try + { + __idGenerators[type] = idGenerator; + } + finally + { + __configLock.ExitWriteLock(); + } + } + + /// + /// Registers a serialization provider. + /// + /// The serialization provider. + public void RegisterSerializationProvider(IBsonSerializationProvider provider) + { + __serializerRegistry.RegisterSerializationProvider(provider); + } + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + public void RegisterSerializer(IBsonSerializer serializer) + { + RegisterSerializer(typeof(T), serializer); + } + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + public void RegisterSerializer(Type type, IBsonSerializer serializer) + { + __serializerRegistry.RegisterSerializer(type, serializer); + } + + /// + /// Serializes a value. + /// + /// The nominal type of the object. + /// The BsonWriter. + /// The object. + /// The serialization context configurator. + /// The serialization args. + public void Serialize( + IBsonWriter bsonWriter, + TNominalType value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)) + { + args.SetOrValidateNominalType(typeof(TNominalType), ""); + var serializer = LookupSerializer(); + var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator); + serializer.Serialize(context, args, value); + } + + /// + /// Serializes a value. + /// + /// The BsonWriter. + /// The nominal type of the object. + /// The object. + /// The serialization context configurator. + /// The serialization args. + public void Serialize( + IBsonWriter bsonWriter, + Type nominalType, + object value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)) + { + args.SetOrValidateNominalType(nominalType, "nominalType"); + var serializer = LookupSerializer(nominalType); + var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator); + serializer.Serialize(context, args, value); + } + + /// + /// Tries to register a serializer for a type. + /// + /// The serializer. + /// The type. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + public bool TryRegisterSerializer(Type type, IBsonSerializer serializer) + { + return __serializerRegistry.TryRegisterSerializer(type, serializer); + } + + /// + /// Tries to register a serializer for a type. + /// + /// The type. + /// The serializer. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + public bool TryRegisterSerializer(IBsonSerializer serializer) + { + return TryRegisterSerializer(typeof(T), serializer); + } + + // internal methods + internal void EnsureKnownTypesAreRegistered(Type nominalType) + { + if (__typesWithRegisteredKnownTypes.ContainsKey(nominalType)) + { + return; + } + + __configLock.EnterWriteLock(); + try + { + if (!__typesWithRegisteredKnownTypes.ContainsKey(nominalType)) + { + // only call LookupClassMap for classes with a BsonKnownTypesAttribute + var hasKnownTypesAttribute = nominalType.GetTypeInfo() + .GetCustomAttributes(typeof(BsonKnownTypesAttribute), inherit: false).Any(); + if (hasKnownTypesAttribute) + { + // try and force a scan of the known types + LookupSerializer(nominalType); + } + + // NOTE: The nominalType MUST be added to __typesWithRegisteredKnownTypes after all registration + // work is done to ensure that other threads don't access a partially registered nominalType + // when performing the initial check above outside the __config lock. + __typesWithRegisteredKnownTypes[nominalType] = null; + } + } + finally + { + __configLock.ExitWriteLock(); + } + } + + // private methods + private void CreateSerializerRegistry() + { + __serializerRegistry = new BsonSerializerRegistry(); + __typeMappingSerializationProvider = new TypeMappingSerializationProvider(); + + // order matters. It's in reverse order of how they'll get consumed + __serializerRegistry.RegisterSerializationProvider(new BsonClassMapSerializationProvider()); + __serializerRegistry.RegisterSerializationProvider(new DiscriminatedInterfaceSerializationProvider()); + __serializerRegistry.RegisterSerializationProvider(new CollectionsSerializationProvider()); + __serializerRegistry.RegisterSerializationProvider(new PrimitiveSerializationProvider()); + __serializerRegistry.RegisterSerializationProvider(new AttributedSerializationProvider()); + __serializerRegistry.RegisterSerializationProvider(__typeMappingSerializationProvider); + __serializerRegistry.RegisterSerializationProvider(new BsonObjectModelSerializationProvider()); + } + + private void RegisterIdGenerators() + { + RegisterIdGenerator(typeof(BsonObjectId), BsonObjectIdGenerator.Instance); + RegisterIdGenerator(typeof(Guid), GuidGenerator.Instance); + RegisterIdGenerator(typeof(ObjectId), ObjectIdGenerator.Instance); + } + } +} \ No newline at end of file From a3179941b122963e9d5d3d706073a8772b134c0e Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:21:09 +0100 Subject: [PATCH 04/49] Delegating all the methods to the BsonSerializationManager --- ...Manager.cs => BsonSerializationManager.cs} | 4 +- .../Serialization/BsonSerializer.cs | 542 ++---------------- 2 files changed, 44 insertions(+), 502 deletions(-) rename src/MongoDB.Bson/Serialization/{BsonSerializerManager.cs => BsonSerializationManager.cs} (99%) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializerManager.cs b/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs similarity index 99% rename from src/MongoDB.Bson/Serialization/BsonSerializerManager.cs rename to src/MongoDB.Bson/Serialization/BsonSerializationManager.cs index cd4ea765e70..c20a2587471 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializerManager.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs @@ -15,7 +15,7 @@ namespace MongoDB.Bson.Serialization /// /// A class that represents the BSON serialization functionality. /// - public class BsonSerializerManager + internal class BsonSerializationManager { // private fields private ReaderWriterLockSlim __configLock = @@ -42,7 +42,7 @@ public class BsonSerializerManager private bool __useZeroIdChecker = false; // constructor - BsonSerializerManager() + public BsonSerializationManager() { CreateSerializerRegistry(); RegisterIdGenerators(); diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index b10676062f4..6993ba492d8 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -14,18 +14,10 @@ */ using System; -using System.Collections.Concurrent; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Reflection; using System.Threading; - -// don't add using statement for MongoDB.Bson.Serialization.Serializers to minimize dependencies on DefaultSerializer using MongoDB.Bson.IO; -using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Conventions; -using MongoDB.Bson.Serialization.IdGenerators; namespace MongoDB.Bson.Serialization { @@ -34,43 +26,27 @@ namespace MongoDB.Bson.Serialization /// public static class BsonSerializer { - // private static fields - private static ReaderWriterLockSlim __configLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); - private static Dictionary __idGenerators = new Dictionary(); - private static Dictionary __discriminatorConventions = new Dictionary(); - private static Dictionary> __discriminators = new Dictionary>(); - private static HashSet __discriminatedTypes = new HashSet(); - private static BsonSerializerRegistry __serializerRegistry; - private static TypeMappingSerializationProvider __typeMappingSerializationProvider; - // ConcurrentDictionary is being used as a concurrent set of Type. The values will always be null. - private static ConcurrentDictionary __typesWithRegisteredKnownTypes = new ConcurrentDictionary(); - - private static bool __useNullIdChecker = false; - private static bool __useZeroIdChecker = false; + private static readonly BsonSerializationManager _manager; // static constructor static BsonSerializer() { - CreateSerializerRegistry(); - RegisterIdGenerators(); + _manager = new BsonSerializationManager(); } // public static properties /// /// Gets the serializer registry. /// - public static IBsonSerializerRegistry SerializerRegistry - { - get { return __serializerRegistry; } - } + public static IBsonSerializerRegistry SerializerRegistry => _manager.SerializerRegistry; /// /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. /// public static bool UseNullIdChecker { - get { return __useNullIdChecker; } - set { __useNullIdChecker = value; } + get => _manager.UseNullIdChecker; + set => _manager.UseNullIdChecker = value; } /// @@ -78,15 +54,12 @@ public static bool UseNullIdChecker /// public static bool UseZeroIdChecker { - get { return __useZeroIdChecker; } - set { __useZeroIdChecker = value; } + get => _manager.UseZeroIdChecker; + set => _manager.UseZeroIdChecker = value; } // internal static properties - internal static ReaderWriterLockSlim ConfigLock - { - get { return __configLock; } - } + internal static ReaderWriterLockSlim ConfigLock => _manager.ConfigLock; // public static methods /// @@ -97,12 +70,7 @@ internal static ReaderWriterLockSlim ConfigLock /// The configurator. /// A deserialized value. public static TNominalType Deserialize(BsonDocument document, Action configurator = null) - { - using (var bsonReader = new BsonDocumentReader(document)) - { - return Deserialize(bsonReader, configurator); - } - } + => _manager.Deserialize(document, configurator); /// /// Deserializes a value. @@ -112,11 +80,7 @@ public static TNominalType Deserialize(BsonDocument document, Acti /// The configurator. /// A deserialized value. public static TNominalType Deserialize(IBsonReader bsonReader, Action configurator = null) - { - var serializer = LookupSerializer(); - var context = BsonDeserializationContext.CreateRoot(bsonReader, configurator); - return serializer.Deserialize(context); - } + => _manager.Deserialize(bsonReader, configurator); /// /// Deserializes an object from a BSON byte array. @@ -126,13 +90,7 @@ public static TNominalType Deserialize(IBsonReader bsonReader, Act /// The configurator. /// A deserialized value. public static TNominalType Deserialize(byte[] bytes, Action configurator = null) - { - using (var buffer = new ByteArrayBuffer(bytes, isReadOnly: true)) - using (var stream = new ByteBufferStream(buffer)) - { - return Deserialize(stream, configurator); - } - } + => _manager.Deserialize(bytes, configurator); /// /// Deserializes an object from a BSON Stream. @@ -142,12 +100,7 @@ public static TNominalType Deserialize(byte[] bytes, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(Stream stream, Action configurator = null) - { - using (var bsonReader = new BsonBinaryReader(stream)) - { - return Deserialize(bsonReader, configurator); - } - } + => _manager.Deserialize(stream, configurator); /// /// Deserializes an object from a JSON string. @@ -157,12 +110,7 @@ public static TNominalType Deserialize(Stream stream, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(string json, Action configurator = null) - { - using (var bsonReader = new JsonReader(json)) - { - return Deserialize(bsonReader, configurator); - } - } + => _manager.Deserialize(json, configurator); /// /// Deserializes an object from a JSON TextReader. @@ -172,12 +120,7 @@ public static TNominalType Deserialize(string json, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(TextReader textReader, Action configurator = null) - { - using (var bsonReader = new JsonReader(textReader)) - { - return Deserialize(bsonReader, configurator); - } - } + => _manager.Deserialize(textReader, configurator); /// /// Deserializes an object from a BsonDocument. @@ -187,12 +130,7 @@ public static TNominalType Deserialize(TextReader textReader, Acti /// The configurator. /// A deserialized value. public static object Deserialize(BsonDocument document, Type nominalType, Action configurator = null) - { - using (var bsonReader = new BsonDocumentReader(document)) - { - return Deserialize(bsonReader, nominalType, configurator); - } - } + => _manager.Deserialize(document, nominalType, configurator); /// /// Deserializes a value. @@ -202,11 +140,7 @@ public static object Deserialize(BsonDocument document, Type nominalType, Action /// The configurator. /// A deserialized value. public static object Deserialize(IBsonReader bsonReader, Type nominalType, Action configurator = null) - { - var serializer = LookupSerializer(nominalType); - var context = BsonDeserializationContext.CreateRoot(bsonReader, configurator); - return serializer.Deserialize(context); - } + => _manager.Deserialize(bsonReader, nominalType, configurator); /// /// Deserializes an object from a BSON byte array. @@ -216,13 +150,7 @@ public static object Deserialize(IBsonReader bsonReader, Type nominalType, Actio /// The configurator. /// A deserialized value. public static object Deserialize(byte[] bytes, Type nominalType, Action configurator = null) - { - using (var buffer = new ByteArrayBuffer(bytes, isReadOnly: true)) - using (var stream = new ByteBufferStream(buffer)) - { - return Deserialize(stream, nominalType, configurator); - } - } + => _manager.Deserialize(bytes, nominalType, configurator); /// /// Deserializes an object from a BSON Stream. @@ -232,12 +160,7 @@ public static object Deserialize(byte[] bytes, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(Stream stream, Type nominalType, Action configurator = null) - { - using (var bsonReader = new BsonBinaryReader(stream)) - { - return Deserialize(bsonReader, nominalType, configurator); - } - } + => _manager.Deserialize(stream, nominalType, configurator); /// /// Deserializes an object from a JSON string. @@ -247,12 +170,7 @@ public static object Deserialize(Stream stream, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(string json, Type nominalType, Action configurator = null) - { - using (var bsonReader = new JsonReader(json)) - { - return Deserialize(bsonReader, nominalType, configurator); - } - } + => _manager.Deserialize(json, nominalType, configurator); /// /// Deserializes an object from a JSON TextReader. @@ -262,57 +180,13 @@ public static object Deserialize(string json, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(TextReader textReader, Type nominalType, Action configurator = null) - { - using (var bsonReader = new JsonReader(textReader)) - { - return Deserialize(bsonReader, nominalType, configurator); - } - } + => _manager.Deserialize(textReader, nominalType, configurator); internal static IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, IDiscriminatorConvention discriminatorConvention) - { - __configLock.EnterReadLock(); - try - { - if (__discriminatorConventions.TryGetValue(type, out var registeredDiscriminatorConvention)) - { - return registeredDiscriminatorConvention; - } - } - finally - { - __configLock.ExitReadLock(); - } - - __configLock.EnterWriteLock(); - try - { - if (__discriminatorConventions.TryGetValue(type, out var registeredDiscrimantorConvention)) - { - return registeredDiscrimantorConvention; - } - - RegisterDiscriminatorConvention(type, discriminatorConvention); - return discriminatorConvention; - } - finally - { - __configLock.ExitWriteLock(); - } - } + => _manager.GetOrRegisterDiscriminatorConvention(type, discriminatorConvention); internal static bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) - { - __configLock.EnterReadLock(); - try - { - return __discriminatorConventions.ContainsKey(type); - } - finally - { - __configLock.ExitReadLock(); - } - } + => _manager.IsDiscriminatorConventionRegisteredAtThisLevel(type); /// /// Returns whether the given type has any discriminators registered for any of its subclasses. @@ -320,10 +194,7 @@ internal static bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) /// A Type. /// True if the type is discriminated. public static bool IsTypeDiscriminated(Type type) - { - var typeInfo = type.GetTypeInfo(); - return typeInfo.IsInterface || __discriminatedTypes.Contains(type); - } + => _manager.IsTypeDiscriminated(type); /// /// Looks up the actual type of an object to be deserialized. @@ -332,73 +203,7 @@ public static bool IsTypeDiscriminated(Type type) /// The discriminator. /// The actual type of the object. public static Type LookupActualType(Type nominalType, BsonValue discriminator) - { - if (discriminator == null) - { - return nominalType; - } - - // note: EnsureKnownTypesAreRegistered handles its own locking so call from outside any lock - EnsureKnownTypesAreRegistered(nominalType); - - __configLock.EnterReadLock(); - try - { - Type actualType = null; - - HashSet hashSet; - var nominalTypeInfo = nominalType.GetTypeInfo(); - if (__discriminators.TryGetValue(discriminator, out hashSet)) - { - foreach (var type in hashSet) - { - if (nominalTypeInfo.IsAssignableFrom(type)) - { - if (actualType == null) - { - actualType = type; - } - else - { - string message = string.Format("Ambiguous discriminator '{0}'.", discriminator); - throw new BsonSerializationException(message); - } - } - } - - // no need for additional checks, we found the right type - if (actualType != null) - { - return actualType; - } - } - - if (discriminator.IsString) - { - actualType = TypeNameDiscriminator.GetActualType(discriminator.AsString); // see if it's a Type name - } - - if (actualType == null) - { - string message = string.Format("Unknown discriminator value '{0}'.", discriminator); - throw new BsonSerializationException(message); - } - - if (!nominalTypeInfo.IsAssignableFrom(actualType)) - { - string message = string.Format( - "Actual type {0} is not assignable to expected type {1}.", - actualType.FullName, nominalType.FullName); - throw new BsonSerializationException(message); - } - - return actualType; - } - finally - { - __configLock.ExitReadLock(); - } - } + => _manager.LookupActualType(nominalType, discriminator); /// /// Looks up the discriminator convention for a type. @@ -406,76 +211,7 @@ public static Type LookupActualType(Type nominalType, BsonValue discriminator) /// The type. /// A discriminator convention. public static IDiscriminatorConvention LookupDiscriminatorConvention(Type type) - { - __configLock.EnterReadLock(); - try - { - IDiscriminatorConvention convention; - if (__discriminatorConventions.TryGetValue(type, out convention)) - { - return convention; - } - } - finally - { - __configLock.ExitReadLock(); - } - - __configLock.EnterWriteLock(); - try - { - IDiscriminatorConvention convention; - if (!__discriminatorConventions.TryGetValue(type, out convention)) - { - var typeInfo = type.GetTypeInfo(); - if (type == typeof(object)) - { - // if there is no convention registered for object register the default one - convention = new ObjectDiscriminatorConvention("_t"); - RegisterDiscriminatorConvention(typeof(object), convention); - } - else if (typeInfo.IsInterface) - { - // TODO: should convention for interfaces be inherited from parent interfaces? - convention = LookupDiscriminatorConvention(typeof(object)); - RegisterDiscriminatorConvention(type, convention); - } - else - { - // inherit the discriminator convention from the closest parent (that isn't object) that has one - // otherwise default to the standard scalar convention - Type parentType = typeInfo.BaseType; - while (true) - { - if (parentType == typeof(object)) - { - convention = StandardDiscriminatorConvention.Scalar; - break; - } - if (__discriminatorConventions.TryGetValue(parentType, out convention)) - { - break; - } - parentType = parentType.GetTypeInfo().BaseType; - } - - // register this convention for all types between this and the parent type where we found the convention - var unregisteredType = type; - while (unregisteredType != parentType) - { - RegisterDiscriminatorConvention(unregisteredType, convention); - unregisteredType = unregisteredType.GetTypeInfo().BaseType; - } - } - } - - return convention; - } - finally - { - __configLock.ExitWriteLock(); - } - } + => _manager.LookupDiscriminatorConvention(type); /// /// Looks up an IdGenerator. @@ -483,78 +219,21 @@ public static IDiscriminatorConvention LookupDiscriminatorConvention(Type type) /// The Id type. /// An IdGenerator for the Id type. public static IIdGenerator LookupIdGenerator(Type type) - { - __configLock.EnterReadLock(); - try - { - IIdGenerator idGenerator; - if (__idGenerators.TryGetValue(type, out idGenerator)) - { - return idGenerator; - } - } - finally - { - __configLock.ExitReadLock(); - } - - __configLock.EnterWriteLock(); - try - { - IIdGenerator idGenerator; - if (!__idGenerators.TryGetValue(type, out idGenerator)) - { - var typeInfo = type.GetTypeInfo(); - if (typeInfo.IsValueType && __useZeroIdChecker) - { - var iEquatableDefinition = typeof(IEquatable<>); - var iEquatableType = iEquatableDefinition.MakeGenericType(type); - if (iEquatableType.GetTypeInfo().IsAssignableFrom(type)) - { - var zeroIdCheckerDefinition = typeof(ZeroIdChecker<>); - var zeroIdCheckerType = zeroIdCheckerDefinition.MakeGenericType(type); - idGenerator = (IIdGenerator)Activator.CreateInstance(zeroIdCheckerType); - } - } - else if (__useNullIdChecker) - { - idGenerator = NullIdChecker.Instance; - } - else - { - idGenerator = null; - } - - __idGenerators[type] = idGenerator; // remember it even if it's null - } - - return idGenerator; - } - finally - { - __configLock.ExitWriteLock(); - } - } + => _manager.LookupIdGenerator(type); /// /// Looks up a serializer for a Type. /// /// The type. /// A serializer for type T. - public static IBsonSerializer LookupSerializer() - { - return (IBsonSerializer)LookupSerializer(typeof(T)); - } + public static IBsonSerializer LookupSerializer() => _manager.LookupSerializer(); /// /// Looks up a serializer for a Type. /// /// The Type. /// A serializer for the Type. - public static IBsonSerializer LookupSerializer(Type type) - { - return __serializerRegistry.GetSerializer(type); - } + public static IBsonSerializer LookupSerializer(Type type) => _manager.LookupSerializer(type); /// /// Registers the discriminator for a type. @@ -562,40 +241,7 @@ public static IBsonSerializer LookupSerializer(Type type) /// The type. /// The discriminator. public static void RegisterDiscriminator(Type type, BsonValue discriminator) - { - var typeInfo = type.GetTypeInfo(); - if (typeInfo.IsInterface) - { - var message = string.Format("Discriminators can only be registered for classes, not for interface {0}.", type.FullName); - throw new BsonSerializationException(message); - } - - __configLock.EnterWriteLock(); - try - { - HashSet hashSet; - if (!__discriminators.TryGetValue(discriminator, out hashSet)) - { - hashSet = new HashSet(); - __discriminators.Add(discriminator, hashSet); - } - - if (!hashSet.Contains(type)) - { - hashSet.Add(type); - - // mark all base types as discriminated (so we know that it's worth reading a discriminator) - for (var baseType = typeInfo.BaseType; baseType != null; baseType = baseType.GetTypeInfo().BaseType) - { - __discriminatedTypes.Add(baseType); - } - } - } - finally - { - __configLock.ExitWriteLock(); - } - } + => _manager.RegisterDiscriminator(type, discriminator); /// /// Registers the discriminator convention for a type. @@ -603,37 +249,15 @@ public static void RegisterDiscriminator(Type type, BsonValue discriminator) /// Type type. /// The discriminator convention. public static void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention) - { - __configLock.EnterWriteLock(); - try - { - if (!__discriminatorConventions.ContainsKey(type)) - { - __discriminatorConventions.Add(type, convention); - } - else - { - var message = string.Format("There is already a discriminator convention registered for type {0}.", type.FullName); - throw new BsonSerializationException(message); - } - } - finally - { - __configLock.ExitWriteLock(); - } - } + => _manager.RegisterDiscriminatorConvention(type, convention); /// /// Registers a generic serializer definition for a generic type. /// /// The generic type. /// The generic serializer definition. - public static void RegisterGenericSerializerDefinition( - Type genericTypeDefinition, - Type genericSerializerDefinition) - { - __typeMappingSerializationProvider.RegisterMapping(genericTypeDefinition, genericSerializerDefinition); - } + public static void RegisterGenericSerializerDefinition(Type genericTypeDefinition, Type genericSerializerDefinition) + => _manager.RegisterGenericSerializerDefinition(genericTypeDefinition, genericSerializerDefinition); /// /// Registers an IdGenerator for an Id Type. @@ -641,26 +265,14 @@ public static void RegisterGenericSerializerDefinition( /// The Id Type. /// The IdGenerator for the Id Type. public static void RegisterIdGenerator(Type type, IIdGenerator idGenerator) - { - __configLock.EnterWriteLock(); - try - { - __idGenerators[type] = idGenerator; - } - finally - { - __configLock.ExitWriteLock(); - } - } + => _manager.RegisterIdGenerator(type, idGenerator); /// /// Registers a serialization provider. /// /// The serialization provider. public static void RegisterSerializationProvider(IBsonSerializationProvider provider) - { - __serializerRegistry.RegisterSerializationProvider(provider); - } + => _manager.RegisterSerializationProvider(provider); /// /// Registers a serializer for a type. @@ -668,9 +280,7 @@ public static void RegisterSerializationProvider(IBsonSerializationProvider prov /// The type. /// The serializer. public static void RegisterSerializer(IBsonSerializer serializer) - { - RegisterSerializer(typeof(T), serializer); - } + => _manager.RegisterSerializer(serializer); /// /// Registers a serializer for a type. @@ -678,9 +288,7 @@ public static void RegisterSerializer(IBsonSerializer serializer) /// The type. /// The serializer. public static void RegisterSerializer(Type type, IBsonSerializer serializer) - { - __serializerRegistry.RegisterSerializer(type, serializer); - } + => _manager.RegisterSerializer(type, serializer); /// /// Serializes a value. @@ -694,13 +302,8 @@ public static void Serialize( IBsonWriter bsonWriter, TNominalType value, Action configurator = null, - BsonSerializationArgs args = default(BsonSerializationArgs)) - { - args.SetOrValidateNominalType(typeof(TNominalType), ""); - var serializer = LookupSerializer(); - var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator); - serializer.Serialize(context, args, value); - } + BsonSerializationArgs args = default) + => _manager.Serialize(bsonWriter, value, configurator, args); /// /// Serializes a value. @@ -716,12 +319,7 @@ public static void Serialize( object value, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)) - { - args.SetOrValidateNominalType(nominalType, "nominalType"); - var serializer = LookupSerializer(nominalType); - var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator); - serializer.Serialize(context, args, value); - } + => _manager.Serialize(bsonWriter, nominalType, value, configurator, args); /// /// Tries to register a serializer for a type. @@ -730,9 +328,7 @@ public static void Serialize( /// The type. /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. public static bool TryRegisterSerializer(Type type, IBsonSerializer serializer) - { - return __serializerRegistry.TryRegisterSerializer(type, serializer); - } + => _manager.TryRegisterSerializer(type, serializer); /// /// Tries to register a serializer for a type. @@ -741,64 +337,10 @@ public static bool TryRegisterSerializer(Type type, IBsonSerializer serializer) /// The serializer. /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. public static bool TryRegisterSerializer(IBsonSerializer serializer) - { - return TryRegisterSerializer(typeof(T), serializer); - } + => _manager.TryRegisterSerializer(serializer); // internal static methods internal static void EnsureKnownTypesAreRegistered(Type nominalType) - { - if (__typesWithRegisteredKnownTypes.ContainsKey(nominalType)) - { - return; - } - - __configLock.EnterWriteLock(); - try - { - if (!__typesWithRegisteredKnownTypes.ContainsKey(nominalType)) - { - // only call LookupClassMap for classes with a BsonKnownTypesAttribute - var hasKnownTypesAttribute = nominalType.GetTypeInfo().GetCustomAttributes(typeof(BsonKnownTypesAttribute), inherit: false).Any(); - if (hasKnownTypesAttribute) - { - // try and force a scan of the known types - LookupSerializer(nominalType); - } - - // NOTE: The nominalType MUST be added to __typesWithRegisteredKnownTypes after all registration - // work is done to ensure that other threads don't access a partially registered nominalType - // when performing the initial check above outside the __config lock. - __typesWithRegisteredKnownTypes[nominalType] = null; - } - } - finally - { - __configLock.ExitWriteLock(); - } - } - - // private static methods - private static void CreateSerializerRegistry() - { - __serializerRegistry = new BsonSerializerRegistry(); - __typeMappingSerializationProvider = new TypeMappingSerializationProvider(); - - // order matters. It's in reverse order of how they'll get consumed - __serializerRegistry.RegisterSerializationProvider(new BsonClassMapSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new DiscriminatedInterfaceSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new CollectionsSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new PrimitiveSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new AttributedSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(__typeMappingSerializationProvider); - __serializerRegistry.RegisterSerializationProvider(new BsonObjectModelSerializationProvider()); - } - - private static void RegisterIdGenerators() - { - RegisterIdGenerator(typeof(BsonObjectId), BsonObjectIdGenerator.Instance); - RegisterIdGenerator(typeof(Guid), GuidGenerator.Instance); - RegisterIdGenerator(typeof(ObjectId), ObjectIdGenerator.Instance); - } + => _manager.EnsureKnownTypesAreRegistered(nominalType); } } From 0e2f7b95e8477111b95da34c019398b210171067 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:29:16 +0100 Subject: [PATCH 05/49] Added interface --- .../Serialization/BsonSerializationManager.cs | 2 +- .../IBsonSerializationManager.cs | 282 ++++++++++++++++++ 2 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 src/MongoDB.Bson/Serialization/IBsonSerializationManager.cs diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs b/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs index c20a2587471..8cdd6686bb6 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs @@ -15,7 +15,7 @@ namespace MongoDB.Bson.Serialization /// /// A class that represents the BSON serialization functionality. /// - internal class BsonSerializationManager + internal class BsonSerializationManager : IBsonSerializationManager { // private fields private ReaderWriterLockSlim __configLock = diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationManager.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationManager.cs new file mode 100644 index 00000000000..39dc1c1ed4a --- /dev/null +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationManager.cs @@ -0,0 +1,282 @@ +using System; +using System.IO; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Conventions; + +namespace MongoDB.Bson.Serialization; + +internal interface IBsonSerializationManager +{ + /// + /// Gets the serializer registry. + /// + IBsonSerializerRegistry SerializerRegistry { get; } + + /// + /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// + bool UseNullIdChecker { get; set; } + + /// + /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// + bool UseZeroIdChecker { get; set; } + + /// + /// Deserializes an object from a BsonDocument. + /// + /// The nominal type of the object. + /// The BsonDocument. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(BsonDocument document, + Action configurator = null); + + /// + /// Deserializes a value. + /// + /// The nominal type of the object. + /// The BsonReader. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(IBsonReader bsonReader, + Action configurator = null); + + /// + /// Deserializes an object from a BSON byte array. + /// + /// The nominal type of the object. + /// The BSON byte array. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(byte[] bytes, + Action configurator = null); + + /// + /// Deserializes an object from a BSON Stream. + /// + /// The nominal type of the object. + /// The BSON Stream. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(Stream stream, + Action configurator = null); + + /// + /// Deserializes an object from a JSON string. + /// + /// The nominal type of the object. + /// The JSON string. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(string json, + Action configurator = null); + + /// + /// Deserializes an object from a JSON TextReader. + /// + /// The nominal type of the object. + /// The JSON TextReader. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(TextReader textReader, + Action configurator = null); + + /// + /// Deserializes an object from a BsonDocument. + /// + /// The BsonDocument. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(BsonDocument document, Type nominalType, + Action configurator = null); + + /// + /// Deserializes a value. + /// + /// The BsonReader. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(IBsonReader bsonReader, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a BSON byte array. + /// + /// The BSON byte array. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(byte[] bytes, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a BSON Stream. + /// + /// The BSON Stream. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(Stream stream, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a JSON string. + /// + /// The JSON string. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(string json, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a JSON TextReader. + /// + /// The JSON TextReader. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(TextReader textReader, Type nominalType, + Action configurator = null); + + /// + /// Returns whether the given type has any discriminators registered for any of its subclasses. + /// + /// A Type. + /// True if the type is discriminated. + bool IsTypeDiscriminated(Type type); + + /// + /// Looks up the actual type of an object to be deserialized. + /// + /// The nominal type of the object. + /// The discriminator. + /// The actual type of the object. + Type LookupActualType(Type nominalType, BsonValue discriminator); + + /// + /// Looks up the discriminator convention for a type. + /// + /// The type. + /// A discriminator convention. + IDiscriminatorConvention LookupDiscriminatorConvention(Type type); + + /// + /// Looks up an IdGenerator. + /// + /// The Id type. + /// An IdGenerator for the Id type. + IIdGenerator LookupIdGenerator(Type type); + + /// + /// Looks up a serializer for a Type. + /// + /// The type. + /// A serializer for type T. + IBsonSerializer LookupSerializer(); + + /// + /// Looks up a serializer for a Type. + /// + /// The Type. + /// A serializer for the Type. + IBsonSerializer LookupSerializer(Type type); + + /// + /// Registers the discriminator for a type. + /// + /// The type. + /// The discriminator. + void RegisterDiscriminator(Type type, BsonValue discriminator); + + /// + /// Registers the discriminator convention for a type. + /// + /// Type type. + /// The discriminator convention. + void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); + + /// + /// Registers a generic serializer definition for a generic type. + /// + /// The generic type. + /// The generic serializer definition. + void RegisterGenericSerializerDefinition( + Type genericTypeDefinition, + Type genericSerializerDefinition); + + /// + /// Registers an IdGenerator for an Id Type. + /// + /// The Id Type. + /// The IdGenerator for the Id Type. + void RegisterIdGenerator(Type type, IIdGenerator idGenerator); + + /// + /// Registers a serialization provider. + /// + /// The serialization provider. + void RegisterSerializationProvider(IBsonSerializationProvider provider); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(IBsonSerializer serializer); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Serializes a value. + /// + /// The nominal type of the object. + /// The BsonWriter. + /// The object. + /// The serialization context configurator. + /// The serialization args. + void Serialize( + IBsonWriter bsonWriter, + TNominalType value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)); + + /// + /// Serializes a value. + /// + /// The BsonWriter. + /// The nominal type of the object. + /// The object. + /// The serialization context configurator. + /// The serialization args. + void Serialize( + IBsonWriter bsonWriter, + Type nominalType, + object value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)); + + /// + /// Tries to register a serializer for a type. + /// + /// The serializer. + /// The type. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Tries to register a serializer for a type. + /// + /// The type. + /// The serializer. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(IBsonSerializer serializer); +} \ No newline at end of file From a051d188ecc78a801b816741ed4b1f0a0b091171 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:36:25 +0100 Subject: [PATCH 06/49] Small fix --- src/MongoDB.Bson/Serialization/BsonSerializationManager.cs | 7 ++++++- src/MongoDB.Bson/Serialization/BsonSerializer.cs | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs b/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs index 8cdd6686bb6..1f641005cba 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs @@ -15,7 +15,7 @@ namespace MongoDB.Bson.Serialization /// /// A class that represents the BSON serialization functionality. /// - internal class BsonSerializationManager : IBsonSerializationManager + internal class BsonSerializationManager : IBsonSerializationManager, IDisposable { // private fields private ReaderWriterLockSlim __configLock = @@ -789,6 +789,11 @@ internal void EnsureKnownTypesAreRegistered(Type nominalType) } } + public void Dispose() + { + __configLock.Dispose(); + } + // private methods private void CreateSerializerRegistry() { diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index 6993ba492d8..7d640ccd479 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -34,6 +34,8 @@ static BsonSerializer() _manager = new BsonSerializationManager(); } + internal static IBsonSerializationManager Manager => _manager; + // public static properties /// /// Gets the serializer registry. From bb60887c07a031d44d355f7d8c3c4e0f53d3d0be Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:58:33 +0100 Subject: [PATCH 07/49] Rename --- ...nManager.cs => BsonSerializationDomain.cs} | 4 +- .../Serialization/BsonSerializer.cs | 82 +++++++++---------- ...Manager.cs => IBsonSerializationDomain.cs} | 2 +- 3 files changed, 44 insertions(+), 44 deletions(-) rename src/MongoDB.Bson/Serialization/{BsonSerializationManager.cs => BsonSerializationDomain.cs} (99%) rename src/MongoDB.Bson/Serialization/{IBsonSerializationManager.cs => IBsonSerializationDomain.cs} (99%) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs similarity index 99% rename from src/MongoDB.Bson/Serialization/BsonSerializationManager.cs rename to src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 1f641005cba..068aeac3ded 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationManager.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -15,7 +15,7 @@ namespace MongoDB.Bson.Serialization /// /// A class that represents the BSON serialization functionality. /// - internal class BsonSerializationManager : IBsonSerializationManager, IDisposable + internal class BsonSerializationDomain : IBsonSerializationDomain, IDisposable { // private fields private ReaderWriterLockSlim __configLock = @@ -42,7 +42,7 @@ internal class BsonSerializationManager : IBsonSerializationManager, IDisposable private bool __useZeroIdChecker = false; // constructor - public BsonSerializationManager() + public BsonSerializationDomain() { CreateSerializerRegistry(); RegisterIdGenerators(); diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index 7d640ccd479..00516ea058e 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -26,29 +26,29 @@ namespace MongoDB.Bson.Serialization /// public static class BsonSerializer { - private static readonly BsonSerializationManager _manager; + private static readonly BsonSerializationDomain _domain; // static constructor static BsonSerializer() { - _manager = new BsonSerializationManager(); + _domain = new BsonSerializationDomain(); } - internal static IBsonSerializationManager Manager => _manager; + internal static IBsonSerializationDomain Domain => _domain; // public static properties /// /// Gets the serializer registry. /// - public static IBsonSerializerRegistry SerializerRegistry => _manager.SerializerRegistry; + public static IBsonSerializerRegistry SerializerRegistry => _domain.SerializerRegistry; /// /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. /// public static bool UseNullIdChecker { - get => _manager.UseNullIdChecker; - set => _manager.UseNullIdChecker = value; + get => _domain.UseNullIdChecker; + set => _domain.UseNullIdChecker = value; } /// @@ -56,12 +56,12 @@ public static bool UseNullIdChecker /// public static bool UseZeroIdChecker { - get => _manager.UseZeroIdChecker; - set => _manager.UseZeroIdChecker = value; + get => _domain.UseZeroIdChecker; + set => _domain.UseZeroIdChecker = value; } // internal static properties - internal static ReaderWriterLockSlim ConfigLock => _manager.ConfigLock; + internal static ReaderWriterLockSlim ConfigLock => _domain.ConfigLock; // public static methods /// @@ -72,7 +72,7 @@ public static bool UseZeroIdChecker /// The configurator. /// A deserialized value. public static TNominalType Deserialize(BsonDocument document, Action configurator = null) - => _manager.Deserialize(document, configurator); + => _domain.Deserialize(document, configurator); /// /// Deserializes a value. @@ -82,7 +82,7 @@ public static TNominalType Deserialize(BsonDocument document, Acti /// The configurator. /// A deserialized value. public static TNominalType Deserialize(IBsonReader bsonReader, Action configurator = null) - => _manager.Deserialize(bsonReader, configurator); + => _domain.Deserialize(bsonReader, configurator); /// /// Deserializes an object from a BSON byte array. @@ -92,7 +92,7 @@ public static TNominalType Deserialize(IBsonReader bsonReader, Act /// The configurator. /// A deserialized value. public static TNominalType Deserialize(byte[] bytes, Action configurator = null) - => _manager.Deserialize(bytes, configurator); + => _domain.Deserialize(bytes, configurator); /// /// Deserializes an object from a BSON Stream. @@ -102,7 +102,7 @@ public static TNominalType Deserialize(byte[] bytes, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(Stream stream, Action configurator = null) - => _manager.Deserialize(stream, configurator); + => _domain.Deserialize(stream, configurator); /// /// Deserializes an object from a JSON string. @@ -112,7 +112,7 @@ public static TNominalType Deserialize(Stream stream, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(string json, Action configurator = null) - => _manager.Deserialize(json, configurator); + => _domain.Deserialize(json, configurator); /// /// Deserializes an object from a JSON TextReader. @@ -122,7 +122,7 @@ public static TNominalType Deserialize(string json, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(TextReader textReader, Action configurator = null) - => _manager.Deserialize(textReader, configurator); + => _domain.Deserialize(textReader, configurator); /// /// Deserializes an object from a BsonDocument. @@ -132,7 +132,7 @@ public static TNominalType Deserialize(TextReader textReader, Acti /// The configurator. /// A deserialized value. public static object Deserialize(BsonDocument document, Type nominalType, Action configurator = null) - => _manager.Deserialize(document, nominalType, configurator); + => _domain.Deserialize(document, nominalType, configurator); /// /// Deserializes a value. @@ -142,7 +142,7 @@ public static object Deserialize(BsonDocument document, Type nominalType, Action /// The configurator. /// A deserialized value. public static object Deserialize(IBsonReader bsonReader, Type nominalType, Action configurator = null) - => _manager.Deserialize(bsonReader, nominalType, configurator); + => _domain.Deserialize(bsonReader, nominalType, configurator); /// /// Deserializes an object from a BSON byte array. @@ -152,7 +152,7 @@ public static object Deserialize(IBsonReader bsonReader, Type nominalType, Actio /// The configurator. /// A deserialized value. public static object Deserialize(byte[] bytes, Type nominalType, Action configurator = null) - => _manager.Deserialize(bytes, nominalType, configurator); + => _domain.Deserialize(bytes, nominalType, configurator); /// /// Deserializes an object from a BSON Stream. @@ -162,7 +162,7 @@ public static object Deserialize(byte[] bytes, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(Stream stream, Type nominalType, Action configurator = null) - => _manager.Deserialize(stream, nominalType, configurator); + => _domain.Deserialize(stream, nominalType, configurator); /// /// Deserializes an object from a JSON string. @@ -172,7 +172,7 @@ public static object Deserialize(Stream stream, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(string json, Type nominalType, Action configurator = null) - => _manager.Deserialize(json, nominalType, configurator); + => _domain.Deserialize(json, nominalType, configurator); /// /// Deserializes an object from a JSON TextReader. @@ -182,13 +182,13 @@ public static object Deserialize(string json, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(TextReader textReader, Type nominalType, Action configurator = null) - => _manager.Deserialize(textReader, nominalType, configurator); + => _domain.Deserialize(textReader, nominalType, configurator); internal static IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, IDiscriminatorConvention discriminatorConvention) - => _manager.GetOrRegisterDiscriminatorConvention(type, discriminatorConvention); + => _domain.GetOrRegisterDiscriminatorConvention(type, discriminatorConvention); internal static bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) - => _manager.IsDiscriminatorConventionRegisteredAtThisLevel(type); + => _domain.IsDiscriminatorConventionRegisteredAtThisLevel(type); /// /// Returns whether the given type has any discriminators registered for any of its subclasses. @@ -196,7 +196,7 @@ internal static bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) /// A Type. /// True if the type is discriminated. public static bool IsTypeDiscriminated(Type type) - => _manager.IsTypeDiscriminated(type); + => _domain.IsTypeDiscriminated(type); /// /// Looks up the actual type of an object to be deserialized. @@ -205,7 +205,7 @@ public static bool IsTypeDiscriminated(Type type) /// The discriminator. /// The actual type of the object. public static Type LookupActualType(Type nominalType, BsonValue discriminator) - => _manager.LookupActualType(nominalType, discriminator); + => _domain.LookupActualType(nominalType, discriminator); /// /// Looks up the discriminator convention for a type. @@ -213,7 +213,7 @@ public static Type LookupActualType(Type nominalType, BsonValue discriminator) /// The type. /// A discriminator convention. public static IDiscriminatorConvention LookupDiscriminatorConvention(Type type) - => _manager.LookupDiscriminatorConvention(type); + => _domain.LookupDiscriminatorConvention(type); /// /// Looks up an IdGenerator. @@ -221,21 +221,21 @@ public static IDiscriminatorConvention LookupDiscriminatorConvention(Type type) /// The Id type. /// An IdGenerator for the Id type. public static IIdGenerator LookupIdGenerator(Type type) - => _manager.LookupIdGenerator(type); + => _domain.LookupIdGenerator(type); /// /// Looks up a serializer for a Type. /// /// The type. /// A serializer for type T. - public static IBsonSerializer LookupSerializer() => _manager.LookupSerializer(); + public static IBsonSerializer LookupSerializer() => _domain.LookupSerializer(); /// /// Looks up a serializer for a Type. /// /// The Type. /// A serializer for the Type. - public static IBsonSerializer LookupSerializer(Type type) => _manager.LookupSerializer(type); + public static IBsonSerializer LookupSerializer(Type type) => _domain.LookupSerializer(type); /// /// Registers the discriminator for a type. @@ -243,7 +243,7 @@ public static IIdGenerator LookupIdGenerator(Type type) /// The type. /// The discriminator. public static void RegisterDiscriminator(Type type, BsonValue discriminator) - => _manager.RegisterDiscriminator(type, discriminator); + => _domain.RegisterDiscriminator(type, discriminator); /// /// Registers the discriminator convention for a type. @@ -251,7 +251,7 @@ public static void RegisterDiscriminator(Type type, BsonValue discriminator) /// Type type. /// The discriminator convention. public static void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention) - => _manager.RegisterDiscriminatorConvention(type, convention); + => _domain.RegisterDiscriminatorConvention(type, convention); /// /// Registers a generic serializer definition for a generic type. @@ -259,7 +259,7 @@ public static void RegisterDiscriminatorConvention(Type type, IDiscriminatorConv /// The generic type. /// The generic serializer definition. public static void RegisterGenericSerializerDefinition(Type genericTypeDefinition, Type genericSerializerDefinition) - => _manager.RegisterGenericSerializerDefinition(genericTypeDefinition, genericSerializerDefinition); + => _domain.RegisterGenericSerializerDefinition(genericTypeDefinition, genericSerializerDefinition); /// /// Registers an IdGenerator for an Id Type. @@ -267,14 +267,14 @@ public static void RegisterGenericSerializerDefinition(Type genericTypeDefinitio /// The Id Type. /// The IdGenerator for the Id Type. public static void RegisterIdGenerator(Type type, IIdGenerator idGenerator) - => _manager.RegisterIdGenerator(type, idGenerator); + => _domain.RegisterIdGenerator(type, idGenerator); /// /// Registers a serialization provider. /// /// The serialization provider. public static void RegisterSerializationProvider(IBsonSerializationProvider provider) - => _manager.RegisterSerializationProvider(provider); + => _domain.RegisterSerializationProvider(provider); /// /// Registers a serializer for a type. @@ -282,7 +282,7 @@ public static void RegisterSerializationProvider(IBsonSerializationProvider prov /// The type. /// The serializer. public static void RegisterSerializer(IBsonSerializer serializer) - => _manager.RegisterSerializer(serializer); + => _domain.RegisterSerializer(serializer); /// /// Registers a serializer for a type. @@ -290,7 +290,7 @@ public static void RegisterSerializer(IBsonSerializer serializer) /// The type. /// The serializer. public static void RegisterSerializer(Type type, IBsonSerializer serializer) - => _manager.RegisterSerializer(type, serializer); + => _domain.RegisterSerializer(type, serializer); /// /// Serializes a value. @@ -305,7 +305,7 @@ public static void Serialize( TNominalType value, Action configurator = null, BsonSerializationArgs args = default) - => _manager.Serialize(bsonWriter, value, configurator, args); + => _domain.Serialize(bsonWriter, value, configurator, args); /// /// Serializes a value. @@ -321,7 +321,7 @@ public static void Serialize( object value, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)) - => _manager.Serialize(bsonWriter, nominalType, value, configurator, args); + => _domain.Serialize(bsonWriter, nominalType, value, configurator, args); /// /// Tries to register a serializer for a type. @@ -330,7 +330,7 @@ public static void Serialize( /// The type. /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. public static bool TryRegisterSerializer(Type type, IBsonSerializer serializer) - => _manager.TryRegisterSerializer(type, serializer); + => _domain.TryRegisterSerializer(type, serializer); /// /// Tries to register a serializer for a type. @@ -339,10 +339,10 @@ public static bool TryRegisterSerializer(Type type, IBsonSerializer serializer) /// The serializer. /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. public static bool TryRegisterSerializer(IBsonSerializer serializer) - => _manager.TryRegisterSerializer(serializer); + => _domain.TryRegisterSerializer(serializer); // internal static methods internal static void EnsureKnownTypesAreRegistered(Type nominalType) - => _manager.EnsureKnownTypesAreRegistered(nominalType); + => _domain.EnsureKnownTypesAreRegistered(nominalType); } } diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationManager.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs similarity index 99% rename from src/MongoDB.Bson/Serialization/IBsonSerializationManager.cs rename to src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index 39dc1c1ed4a..e80bd00f325 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationManager.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -5,7 +5,7 @@ namespace MongoDB.Bson.Serialization; -internal interface IBsonSerializationManager +internal interface IBsonSerializationDomain { /// /// Gets the serializer registry. From 56a9b7e3015d60953c9dcc7f0837fb797fe8c4af Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Fri, 10 Jan 2025 10:35:48 +0100 Subject: [PATCH 08/49] Added internal interface --- .../Serialization/BsonSerializationDomain.cs | 10 +- .../Serialization/BsonSerializer.cs | 3 +- .../Serialization/IBsonSerializationDomain.cs | 565 +++++++++--------- 3 files changed, 298 insertions(+), 280 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 068aeac3ded..5076bc42d9e 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -15,7 +15,7 @@ namespace MongoDB.Bson.Serialization /// /// A class that represents the BSON serialization functionality. /// - internal class BsonSerializationDomain : IBsonSerializationDomain, IDisposable + internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisposable { // private fields private ReaderWriterLockSlim __configLock = @@ -76,7 +76,7 @@ public bool UseZeroIdChecker } // internal properties - internal ReaderWriterLockSlim ConfigLock + public ReaderWriterLockSlim ConfigLock { get { return __configLock; } } @@ -274,7 +274,7 @@ public object Deserialize(TextReader textReader, Type nominalType, } } - internal IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, + public IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, IDiscriminatorConvention discriminatorConvention) { __configLock.EnterReadLock(); @@ -307,7 +307,7 @@ internal IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type } } - internal bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) + public bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) { __configLock.EnterReadLock(); try @@ -756,7 +756,7 @@ public bool TryRegisterSerializer(IBsonSerializer serializer) } // internal methods - internal void EnsureKnownTypesAreRegistered(Type nominalType) + public void EnsureKnownTypesAreRegistered(Type nominalType) { if (__typesWithRegisteredKnownTypes.ContainsKey(nominalType)) { diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index 00516ea058e..0251bf72e57 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -26,7 +26,7 @@ namespace MongoDB.Bson.Serialization /// public static class BsonSerializer { - private static readonly BsonSerializationDomain _domain; + private static readonly IBsonSerializationDomainInternal _domain; // static constructor static BsonSerializer() @@ -34,6 +34,7 @@ static BsonSerializer() _domain = new BsonSerializationDomain(); } + //TODO This will need to be public internal static IBsonSerializationDomain Domain => _domain; // public static properties diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index e80bd00f325..ac0f790e70a 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -1,282 +1,299 @@ using System; using System.IO; +using System.Threading; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization.Conventions; -namespace MongoDB.Bson.Serialization; - -internal interface IBsonSerializationDomain +namespace MongoDB.Bson.Serialization { /// - /// Gets the serializer registry. - /// - IBsonSerializerRegistry SerializerRegistry { get; } - - /// - /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. - /// - bool UseNullIdChecker { get; set; } - - /// - /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. - /// - bool UseZeroIdChecker { get; set; } - - /// - /// Deserializes an object from a BsonDocument. - /// - /// The nominal type of the object. - /// The BsonDocument. - /// The configurator. - /// A deserialized value. - TNominalType Deserialize(BsonDocument document, - Action configurator = null); - - /// - /// Deserializes a value. - /// - /// The nominal type of the object. - /// The BsonReader. - /// The configurator. - /// A deserialized value. - TNominalType Deserialize(IBsonReader bsonReader, - Action configurator = null); - - /// - /// Deserializes an object from a BSON byte array. - /// - /// The nominal type of the object. - /// The BSON byte array. - /// The configurator. - /// A deserialized value. - TNominalType Deserialize(byte[] bytes, - Action configurator = null); - - /// - /// Deserializes an object from a BSON Stream. - /// - /// The nominal type of the object. - /// The BSON Stream. - /// The configurator. - /// A deserialized value. - TNominalType Deserialize(Stream stream, - Action configurator = null); - - /// - /// Deserializes an object from a JSON string. - /// - /// The nominal type of the object. - /// The JSON string. - /// The configurator. - /// A deserialized value. - TNominalType Deserialize(string json, - Action configurator = null); - - /// - /// Deserializes an object from a JSON TextReader. - /// - /// The nominal type of the object. - /// The JSON TextReader. - /// The configurator. - /// A deserialized value. - TNominalType Deserialize(TextReader textReader, - Action configurator = null); - - /// - /// Deserializes an object from a BsonDocument. - /// - /// The BsonDocument. - /// The nominal type of the object. - /// The configurator. - /// A deserialized value. - object Deserialize(BsonDocument document, Type nominalType, - Action configurator = null); - - /// - /// Deserializes a value. - /// - /// The BsonReader. - /// The nominal type of the object. - /// The configurator. - /// A deserialized value. - object Deserialize(IBsonReader bsonReader, Type nominalType, - Action configurator = null); - - /// - /// Deserializes an object from a BSON byte array. - /// - /// The BSON byte array. - /// The nominal type of the object. - /// The configurator. - /// A deserialized value. - object Deserialize(byte[] bytes, Type nominalType, - Action configurator = null); - - /// - /// Deserializes an object from a BSON Stream. - /// - /// The BSON Stream. - /// The nominal type of the object. - /// The configurator. - /// A deserialized value. - object Deserialize(Stream stream, Type nominalType, - Action configurator = null); - - /// - /// Deserializes an object from a JSON string. - /// - /// The JSON string. - /// The nominal type of the object. - /// The configurator. - /// A deserialized value. - object Deserialize(string json, Type nominalType, - Action configurator = null); - - /// - /// Deserializes an object from a JSON TextReader. - /// - /// The JSON TextReader. - /// The nominal type of the object. - /// The configurator. - /// A deserialized value. - object Deserialize(TextReader textReader, Type nominalType, - Action configurator = null); - - /// - /// Returns whether the given type has any discriminators registered for any of its subclasses. - /// - /// A Type. - /// True if the type is discriminated. - bool IsTypeDiscriminated(Type type); - - /// - /// Looks up the actual type of an object to be deserialized. - /// - /// The nominal type of the object. - /// The discriminator. - /// The actual type of the object. - Type LookupActualType(Type nominalType, BsonValue discriminator); - - /// - /// Looks up the discriminator convention for a type. - /// - /// The type. - /// A discriminator convention. - IDiscriminatorConvention LookupDiscriminatorConvention(Type type); - - /// - /// Looks up an IdGenerator. - /// - /// The Id type. - /// An IdGenerator for the Id type. - IIdGenerator LookupIdGenerator(Type type); - - /// - /// Looks up a serializer for a Type. - /// - /// The type. - /// A serializer for type T. - IBsonSerializer LookupSerializer(); - - /// - /// Looks up a serializer for a Type. - /// - /// The Type. - /// A serializer for the Type. - IBsonSerializer LookupSerializer(Type type); - - /// - /// Registers the discriminator for a type. - /// - /// The type. - /// The discriminator. - void RegisterDiscriminator(Type type, BsonValue discriminator); - - /// - /// Registers the discriminator convention for a type. - /// - /// Type type. - /// The discriminator convention. - void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); - - /// - /// Registers a generic serializer definition for a generic type. - /// - /// The generic type. - /// The generic serializer definition. - void RegisterGenericSerializerDefinition( - Type genericTypeDefinition, - Type genericSerializerDefinition); - - /// - /// Registers an IdGenerator for an Id Type. - /// - /// The Id Type. - /// The IdGenerator for the Id Type. - void RegisterIdGenerator(Type type, IIdGenerator idGenerator); - - /// - /// Registers a serialization provider. - /// - /// The serialization provider. - void RegisterSerializationProvider(IBsonSerializationProvider provider); - - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(IBsonSerializer serializer); - - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(Type type, IBsonSerializer serializer); - - /// - /// Serializes a value. - /// - /// The nominal type of the object. - /// The BsonWriter. - /// The object. - /// The serialization context configurator. - /// The serialization args. - void Serialize( - IBsonWriter bsonWriter, - TNominalType value, - Action configurator = null, - BsonSerializationArgs args = default(BsonSerializationArgs)); - - /// - /// Serializes a value. - /// - /// The BsonWriter. - /// The nominal type of the object. - /// The object. - /// The serialization context configurator. - /// The serialization args. - void Serialize( - IBsonWriter bsonWriter, - Type nominalType, - object value, - Action configurator = null, - BsonSerializationArgs args = default(BsonSerializationArgs)); - - /// - /// Tries to register a serializer for a type. - /// - /// The serializer. - /// The type. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(Type type, IBsonSerializer serializer); - - /// - /// Tries to register a serializer for a type. - /// - /// The type. - /// The serializer. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(IBsonSerializer serializer); + /// //TODO + /// + public interface IBsonSerializationDomain + { + /// + /// Gets the serializer registry. + /// + IBsonSerializerRegistry SerializerRegistry { get; } + + /// + /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// + bool UseNullIdChecker { get; set; } + + /// + /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// + bool UseZeroIdChecker { get; set; } + + /// + /// Deserializes an object from a BsonDocument. + /// + /// The nominal type of the object. + /// The BsonDocument. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(BsonDocument document, + Action configurator = null); + + /// + /// Deserializes a value. + /// + /// The nominal type of the object. + /// The BsonReader. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(IBsonReader bsonReader, + Action configurator = null); + + /// + /// Deserializes an object from a BSON byte array. + /// + /// The nominal type of the object. + /// The BSON byte array. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(byte[] bytes, + Action configurator = null); + + /// + /// Deserializes an object from a BSON Stream. + /// + /// The nominal type of the object. + /// The BSON Stream. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(Stream stream, + Action configurator = null); + + /// + /// Deserializes an object from a JSON string. + /// + /// The nominal type of the object. + /// The JSON string. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(string json, + Action configurator = null); + + /// + /// Deserializes an object from a JSON TextReader. + /// + /// The nominal type of the object. + /// The JSON TextReader. + /// The configurator. + /// A deserialized value. + TNominalType Deserialize(TextReader textReader, + Action configurator = null); + + /// + /// Deserializes an object from a BsonDocument. + /// + /// The BsonDocument. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(BsonDocument document, Type nominalType, + Action configurator = null); + + /// + /// Deserializes a value. + /// + /// The BsonReader. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(IBsonReader bsonReader, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a BSON byte array. + /// + /// The BSON byte array. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(byte[] bytes, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a BSON Stream. + /// + /// The BSON Stream. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(Stream stream, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a JSON string. + /// + /// The JSON string. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(string json, Type nominalType, + Action configurator = null); + + /// + /// Deserializes an object from a JSON TextReader. + /// + /// The JSON TextReader. + /// The nominal type of the object. + /// The configurator. + /// A deserialized value. + object Deserialize(TextReader textReader, Type nominalType, + Action configurator = null); + + /// + /// Returns whether the given type has any discriminators registered for any of its subclasses. + /// + /// A Type. + /// True if the type is discriminated. + bool IsTypeDiscriminated(Type type); + + /// + /// Looks up the actual type of an object to be deserialized. + /// + /// The nominal type of the object. + /// The discriminator. + /// The actual type of the object. + Type LookupActualType(Type nominalType, BsonValue discriminator); + + /// + /// Looks up the discriminator convention for a type. + /// + /// The type. + /// A discriminator convention. + IDiscriminatorConvention LookupDiscriminatorConvention(Type type); + + /// + /// Looks up an IdGenerator. + /// + /// The Id type. + /// An IdGenerator for the Id type. + IIdGenerator LookupIdGenerator(Type type); + + /// + /// Looks up a serializer for a Type. + /// + /// The type. + /// A serializer for type T. + IBsonSerializer LookupSerializer(); + + /// + /// Looks up a serializer for a Type. + /// + /// The Type. + /// A serializer for the Type. + IBsonSerializer LookupSerializer(Type type); + + /// + /// Registers the discriminator for a type. + /// + /// The type. + /// The discriminator. + void RegisterDiscriminator(Type type, BsonValue discriminator); + + /// + /// Registers the discriminator convention for a type. + /// + /// Type type. + /// The discriminator convention. + void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); + + /// + /// Registers a generic serializer definition for a generic type. + /// + /// The generic type. + /// The generic serializer definition. + void RegisterGenericSerializerDefinition( + Type genericTypeDefinition, + Type genericSerializerDefinition); + + /// + /// Registers an IdGenerator for an Id Type. + /// + /// The Id Type. + /// The IdGenerator for the Id Type. + void RegisterIdGenerator(Type type, IIdGenerator idGenerator); + + /// + /// Registers a serialization provider. + /// + /// The serialization provider. + void RegisterSerializationProvider(IBsonSerializationProvider provider); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(IBsonSerializer serializer); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Serializes a value. + /// + /// The nominal type of the object. + /// The BsonWriter. + /// The object. + /// The serialization context configurator. + /// The serialization args. + void Serialize( + IBsonWriter bsonWriter, + TNominalType value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)); + + /// + /// Serializes a value. + /// + /// The BsonWriter. + /// The nominal type of the object. + /// The object. + /// The serialization context configurator. + /// The serialization args. + void Serialize( + IBsonWriter bsonWriter, + Type nominalType, + object value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)); + + /// + /// Tries to register a serializer for a type. + /// + /// The serializer. + /// The type. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Tries to register a serializer for a type. + /// + /// The type. + /// The serializer. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(IBsonSerializer serializer); + } + + internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain + { + ReaderWriterLockSlim ConfigLock { get; } + + void EnsureKnownTypesAreRegistered(Type nominalType); + + IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, + IDiscriminatorConvention discriminatorConvention); + + bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type); + } } \ No newline at end of file From 3f634d5724c2ba5dfec939011c2ce2107b34d6f6 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:50:11 +0100 Subject: [PATCH 09/49] Improvements --- src/MongoDB.Bson/BsonDefaults.cs | 2 +- .../BsonDeserializationContext.cs | 25 +++++++++++++++++-- .../Serialization/BsonSerializer.cs | 6 +++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/MongoDB.Bson/BsonDefaults.cs b/src/MongoDB.Bson/BsonDefaults.cs index 9352d3228ff..6abcb6479e5 100644 --- a/src/MongoDB.Bson/BsonDefaults.cs +++ b/src/MongoDB.Bson/BsonDefaults.cs @@ -34,7 +34,7 @@ public static class BsonDefaults // public static properties /// - /// Gets or sets the dynamic array serializer. + /// Gets or sets the dynamic array serializer. //TODO What to we do with this? /// public static IBsonSerializer DynamicArraySerializer { diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index 03ab3137326..f08185af884 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -15,6 +15,8 @@ using System; using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Options; +using MongoDB.Bson.Serialization.Serializers; namespace MongoDB.Bson.Serialization { @@ -28,18 +30,21 @@ public class BsonDeserializationContext private readonly IBsonSerializer _dynamicArraySerializer; private readonly IBsonSerializer _dynamicDocumentSerializer; private readonly IBsonReader _reader; + private readonly IBsonSerializationDomain _domain; // constructors private BsonDeserializationContext( IBsonReader reader, bool allowDuplicateElementNames, IBsonSerializer dynamicArraySerializer, - IBsonSerializer dynamicDocumentSerializer) + IBsonSerializer dynamicDocumentSerializer, + IBsonSerializationDomain domain) { _reader = reader; _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; + _domain = domain; } // public properties @@ -54,6 +59,11 @@ public bool AllowDuplicateElementNames get { return _allowDuplicateElementNames; } } + /// + /// //TODO + /// + public IBsonSerializationDomain Domain => _domain; + /// /// Gets the dynamic array serializer. /// @@ -138,6 +148,7 @@ public class Builder private IBsonSerializer _dynamicArraySerializer; private IBsonSerializer _dynamicDocumentSerializer; private IBsonReader _reader; + private IBsonSerializationDomain _domain; // constructors internal Builder(BsonDeserializationContext other, IBsonReader reader) @@ -153,6 +164,7 @@ internal Builder(BsonDeserializationContext other, IBsonReader reader) _allowDuplicateElementNames = other.AllowDuplicateElementNames; _dynamicArraySerializer = other.DynamicArraySerializer; _dynamicDocumentSerializer = other.DynamicDocumentSerializer; + _domain = other.Domain; } else { @@ -209,6 +221,15 @@ public IBsonReader Reader get { return _reader; } } + /// + /// //TODO + /// + public IBsonSerializationDomain Domain + { + get => _domain; + set => _domain = value; + } + // public methods /// /// Builds the BsonDeserializationContext instance. @@ -216,7 +237,7 @@ public IBsonReader Reader /// A BsonDeserializationContext. internal BsonDeserializationContext Build() { - return new BsonDeserializationContext(_reader, _allowDuplicateElementNames, _dynamicArraySerializer, _dynamicDocumentSerializer); + return new BsonDeserializationContext(_reader, _allowDuplicateElementNames, _dynamicArraySerializer, _dynamicDocumentSerializer, _domain); } } } diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index 0251bf72e57..a2a21042929 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -34,8 +34,10 @@ static BsonSerializer() _domain = new BsonSerializationDomain(); } - //TODO This will need to be public - internal static IBsonSerializationDomain Domain => _domain; + /// + /// //TODO + /// + public static IBsonSerializationDomain DefaultDomain => _domain; // public static properties /// From 550eb9768bce4ba9622160e30dbcf4727bddcbe2 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:04:57 +0100 Subject: [PATCH 10/49] Initial use of domain --- .../Serialization/BsonClassMap.cs | 2 +- .../BsonDeserializationContext.cs | 2 +- .../Serialization/BsonSerializationContext.cs | 23 +++++++++++++++++-- .../Serializers/BsonClassMapSerializer.cs | 4 ++-- .../Serializers/BsonValueSerializerBase.cs | 2 +- .../Serializers/ClassSerializerBase.cs | 4 ++-- .../DiscriminatedInterfaceSerializer.cs | 2 +- .../DiscriminatedWrapperSerializer.cs | 2 +- ...mpliedImplementationInterfaceSerializer.cs | 2 +- .../Serializers/ObjectSerializer.cs | 4 ++-- .../UndiscriminatedActualTypeSerializer.cs | 2 +- 11 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 87239a33bf5..3004f25627d 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -32,7 +32,7 @@ namespace MongoDB.Bson.Serialization public class BsonClassMap { // private static fields - private readonly static Dictionary __classMaps = new Dictionary(); + private readonly static Dictionary __classMaps = new Dictionary(); //TODO I think the static fields and methods should not be here, but on the domain private readonly static Queue __knownTypesQueue = new Queue(); private static int __freezeNestingLevel = 0; diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index f08185af884..2f1d30f9721 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -44,7 +44,7 @@ private BsonDeserializationContext( _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; - _domain = domain; + _domain = domain ?? BsonSerializer.DefaultDomain; //TODO Should we do it here or higher in the hierarchy...? } // public properties diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs index 5ab93777ceb..2b167bc6b7a 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs @@ -26,17 +26,26 @@ public class BsonSerializationContext // private fields private readonly Func _isDynamicType; private readonly IBsonWriter _writer; + private readonly IBsonSerializationDomain _domain; // constructors private BsonSerializationContext( IBsonWriter writer, - Func isDynamicType) + Func isDynamicType, + IBsonSerializationDomain domain) { _writer = writer; _isDynamicType = isDynamicType; + _domain = domain ?? BsonSerializer.DefaultDomain; //TODO Should we do it here or higher in the hierarchy...? } // public properties + + /// + /// //TODO + /// + public IBsonSerializationDomain Domain => _domain; + /// /// Gets a function that, when executed, will indicate whether the type /// is a dynamic type. @@ -105,6 +114,7 @@ public class Builder // private fields private Func _isDynamicType; private IBsonWriter _writer; + private IBsonSerializationDomain _domain; // constructors internal Builder(BsonSerializationContext other, IBsonWriter writer) @@ -127,6 +137,15 @@ internal Builder(BsonSerializationContext other, IBsonWriter writer) } } + /// + /// //TODO + /// + public IBsonSerializationDomain Domain + { + get => _domain; + set => _domain = value; + } + // properties /// /// Gets or sets the function used to determine if a type is a dynamic type. @@ -155,7 +174,7 @@ public IBsonWriter Writer /// A BsonSerializationContext. internal BsonSerializationContext Build() { - return new BsonSerializationContext(_writer, _isDynamicType); + return new BsonSerializationContext(_writer, _isDynamicType, _domain); } } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs index fdcd59916ed..947a4c58369 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs @@ -96,7 +96,7 @@ public override TClass Deserialize(BsonDeserializationContext context, BsonDeser return DeserializeClass(context); } - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); return (TClass)serializer.Deserialize(context); } @@ -392,7 +392,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati return; } - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); serializer.Serialize(context, args, value); } diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs index e3a5776870c..4373f7b0543 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs @@ -70,7 +70,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati var actualType = value.GetType(); if (actualType != ValueType && !args.SerializeAsNominalType) { - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); serializer.Serialize(context, value); return; } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs index 07723b9cddb..39ac5184e9c 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs @@ -47,7 +47,7 @@ public override TValue Deserialize(BsonDeserializationContext context, BsonDeser } else { - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); return (TValue)serializer.Deserialize(context, args); } } @@ -75,7 +75,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati } else { - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); serializer.Serialize(context, value); } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs index ca2fef6fe07..87a6d67f057 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs @@ -147,7 +147,7 @@ public override TInterface Deserialize(BsonDeserializationContext context, BsonD throw new FormatException(message); } - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); return (TInterface)serializer.Deserialize(context, args); } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs index d7d5be76596..da40cf24480 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs @@ -74,7 +74,7 @@ public override TValue Deserialize(BsonDeserializationContext context, BsonDeser var bsonReader = context.Reader; var nominalType = args.NominalType; var actualType = _discriminatorConvention.GetActualType(bsonReader, nominalType); - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); TValue value = default(TValue); _helper.DeserializeMembers(context, (elementName, flag) => diff --git a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs index fc8cdf81829..74f9c72ce95 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs @@ -279,7 +279,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati } else { - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); serializer.Serialize(context, value); } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs index 36e4403718c..a8ccf35277c 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs @@ -389,7 +389,7 @@ private object DeserializeDiscriminatedValue(BsonDeserializationContext context, } else { - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); var polymorphicSerializer = serializer as IBsonPolymorphicSerializer; if (polymorphicSerializer != null && polymorphicSerializer.IsDiscriminatorCompatibleWithObjectSerializer) { @@ -438,7 +438,7 @@ private void SerializeDiscriminatedValue(BsonSerializationContext context, BsonS throw new BsonSerializationException($"Type {actualType.FullName} is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer."); } - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); var polymorphicSerializer = serializer as IBsonPolymorphicSerializer; if (polymorphicSerializer != null && polymorphicSerializer.IsDiscriminatorCompatibleWithObjectSerializer) diff --git a/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs index 1587a979163..8d843ba16de 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs @@ -62,7 +62,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati else { var actualType = value.GetType(); - var serializer = BsonSerializer.LookupSerializer(actualType); + var serializer = context.Domain.LookupSerializer(actualType); args.NominalType = actualType; serializer.Serialize(context, args, value); } From d2e1746ea07311dfa35fca6d11b757a85a91190c Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:59:32 +0100 Subject: [PATCH 11/49] Fix --- src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs | 6 +++--- .../Serialization/BsonDeserializationContext.cs | 3 ++- src/MongoDB.Bson/Serialization/BsonSerializationContext.cs | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs index 09edc32dbfa..12feae4a013 100644 --- a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs +++ b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs @@ -104,7 +104,7 @@ public static BsonDocumentWrapper Create(TNominalType value) /// A BsonDocumentWrapper. public static BsonDocumentWrapper Create(Type nominalType, object value) { - var serializer = BsonSerializer.LookupSerializer(nominalType); + var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think this could stay. We can potentially add methods with the domain as input. return new BsonDocumentWrapper(value, serializer); } @@ -121,7 +121,7 @@ public static IEnumerable CreateMultiple(IEnu throw new ArgumentNullException("values"); } - var serializer = BsonSerializer.LookupSerializer(typeof(TNominalType)); + var serializer = BsonSerializer.LookupSerializer(typeof(TNominalType)); //TODO I think this could stay. We can potentially add methods with the domain as input. return values.Select(v => new BsonDocumentWrapper(v, serializer)); } @@ -142,7 +142,7 @@ public static IEnumerable CreateMultiple(Type nominalType, throw new ArgumentNullException("values"); } - var serializer = BsonSerializer.LookupSerializer(nominalType); + var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think this could stay. We can potentially add methods with the domain as input. return values.Cast().Select(v => new BsonDocumentWrapper(v, serializer)); } diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index 2f1d30f9721..577c309f86d 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -44,7 +44,8 @@ private BsonDeserializationContext( _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; - _domain = domain ?? BsonSerializer.DefaultDomain; //TODO Should we do it here or higher in the hierarchy...? + _domain = domain; + // _domain = domain ?? BsonSerializer.DefaultDomain; //TODO We could do this here, but let's keep it as the previous line to catch errors. } // public properties diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs index 2b167bc6b7a..c327c15b7c3 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs @@ -36,7 +36,8 @@ private BsonSerializationContext( { _writer = writer; _isDynamicType = isDynamicType; - _domain = domain ?? BsonSerializer.DefaultDomain; //TODO Should we do it here or higher in the hierarchy...? + _domain = domain; + // _domain = domain ?? BsonSerializer.DefaultDomain; //TODO We could do this here, but let's keep it as the previous line to catch errors. } // public properties From 8b14426013a8e1263af7497bc448be7e8c413f2f Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 13 Jan 2025 18:24:31 +0100 Subject: [PATCH 12/49] Added comments --- src/MongoDB.Bson/BsonDefaults.cs | 6 +++--- src/MongoDB.Bson/BsonExtensionMethods.cs | 6 +++--- src/MongoDB.Bson/Serialization/BsonClassMap.cs | 2 +- src/MongoDB.Bson/Serialization/BsonMemberMap.cs | 2 +- .../Serialization/BsonSerializationProviderBase.cs | 6 +++--- .../Conventions/ConventionRegistry.cs | 2 +- .../Conventions/LookupIdGeneratorConvention.cs | 2 ++ .../Conventions/ObjectDiscriminatorConvention.cs | 2 +- .../StringIdStoredAsObjectIdConvention.cs | 2 +- .../Serialization/IBsonSerializerExtensions.cs | 2 +- .../Serializers/BsonDocumentSerializer.cs | 2 +- .../Serializers/DictionarySerializerBase.cs | 2 ++ .../DiscriminatedInterfaceSerializer.cs | 4 ++-- .../Serializers/DynamicDocumentBaseSerializer.cs | 14 ++++++++++---- .../Serializers/EnumerableSerializerBase.cs | 4 ++-- .../Serializers/ExpandoObjectSerializer.cs | 3 +-- ...numerableDeserializingAsCollectionSerializer.cs | 2 +- .../ImpliedImplementationInterfaceSerializer.cs | 2 +- .../Serializers/KeyValuePairSerializer.cs | 2 +- .../Serializers/NullableSerializer.cs | 2 +- .../Serialization/Serializers/ObjectSerializer.cs | 4 ++-- .../SerializeAsNominalTypeSerializer.cs | 2 +- .../Serializers/ThreeDimensionalArraySerializer.cs | 2 +- .../Serialization/Serializers/TupleSerializers.cs | 2 +- .../Serializers/TwoDimensionalArraySerializer.cs | 2 +- .../Serializers/ValueTupleSerializers.cs | 2 +- 26 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/MongoDB.Bson/BsonDefaults.cs b/src/MongoDB.Bson/BsonDefaults.cs index 6abcb6479e5..32239ec64a3 100644 --- a/src/MongoDB.Bson/BsonDefaults.cs +++ b/src/MongoDB.Bson/BsonDefaults.cs @@ -34,7 +34,7 @@ public static class BsonDefaults // public static properties /// - /// Gets or sets the dynamic array serializer. //TODO What to we do with this? + /// Gets or sets the dynamic array serializer. /// public static IBsonSerializer DynamicArraySerializer { @@ -42,7 +42,7 @@ public static IBsonSerializer DynamicArraySerializer { if (!__dynamicArraySerializerWasSet) { - __dynamicArraySerializer = BsonSerializer.LookupSerializer>(); + __dynamicArraySerializer = BsonSerializer.LookupSerializer>(); //TODO I think we could keep this as is } return __dynamicArraySerializer; } @@ -62,7 +62,7 @@ public static IBsonSerializer DynamicDocumentSerializer { if (!__dynamicDocumentSerializerWasSet) { - __dynamicDocumentSerializer = BsonSerializer.LookupSerializer(); + __dynamicDocumentSerializer = BsonSerializer.LookupSerializer(); //TODO I think we could keep this as is } return __dynamicDocumentSerializer; } diff --git a/src/MongoDB.Bson/BsonExtensionMethods.cs b/src/MongoDB.Bson/BsonExtensionMethods.cs index bcb41a8271f..c885a81b834 100644 --- a/src/MongoDB.Bson/BsonExtensionMethods.cs +++ b/src/MongoDB.Bson/BsonExtensionMethods.cs @@ -84,7 +84,7 @@ public static byte[] ToBson( if (serializer == null) { - serializer = BsonSerializer.LookupSerializer(nominalType); + serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think we need another method with the domain as input } if (serializer.ValueType != nominalType) { @@ -165,7 +165,7 @@ public static BsonDocument ToBsonDocument( return convertibleToBsonDocument.ToBsonDocument(); // use the provided ToBsonDocument method } - serializer = BsonSerializer.LookupSerializer(nominalType); + serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think we need another method with the domain as input } if (serializer.ValueType != nominalType) { @@ -236,7 +236,7 @@ public static string ToJson( if (serializer == null) { - serializer = BsonSerializer.LookupSerializer(nominalType); + serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think we need another method with the domain as input } if (serializer.ValueType != nominalType) { diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 3004f25627d..07035df3719 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -284,7 +284,7 @@ public static Type GetMemberInfoType(MemberInfo memberInfo) /// All registered class maps. public static IEnumerable GetRegisteredClassMaps() { - BsonSerializer.ConfigLock.EnterReadLock(); + BsonSerializer.ConfigLock.EnterReadLock(); //TODO It would make sense to look at this after the PR by Robert is merged try { return __classMaps.Values.ToList(); // return a copy for thread safety diff --git a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs index b10971d5249..630e0834546 100644 --- a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs @@ -301,7 +301,7 @@ public IBsonSerializer GetSerializer() // return special serializer for BsonValue members that handles the _csharpnull representation if (_memberTypeIsBsonValue) { - var wrappedSerializer = BsonSerializer.LookupSerializer(_memberType); + var wrappedSerializer = BsonSerializer.LookupSerializer(_memberType); //TODO We need another version of this with the domain as input var isBsonArraySerializer = wrappedSerializer is IBsonArraySerializer; var isBsonDocumentSerializer = wrappedSerializer is IBsonDocumentSerializer; diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs b/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs index b2ffb587183..0f3645ac2fe 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs @@ -24,7 +24,7 @@ namespace MongoDB.Bson.Serialization public abstract class BsonSerializationProviderBase : IRegistryAwareBsonSerializationProvider { /// - public virtual IBsonSerializer GetSerializer(Type type) + public virtual IBsonSerializer GetSerializer(Type type) //TODO Need to make another version with the domain as input { return GetSerializer(type, BsonSerializer.SerializerRegistry); } @@ -38,7 +38,7 @@ public virtual IBsonSerializer GetSerializer(Type type) /// The serializer type definition. /// The type arguments. /// A serializer. - protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDefinition, params Type[] typeArguments) + protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDefinition, params Type[] typeArguments) //TODO We need another version of this with the domain as input { return CreateGenericSerializer(serializerTypeDefinition, typeArguments, BsonSerializer.SerializerRegistry); } @@ -65,7 +65,7 @@ protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDef /// A serializer. protected virtual IBsonSerializer CreateSerializer(Type serializerType) { - return CreateSerializer(serializerType, BsonSerializer.SerializerRegistry); + return CreateSerializer(serializerType, BsonSerializer.SerializerRegistry); //TODO We need another version of this with the domain as input } /// diff --git a/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs b/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs index f54934d6ed3..a938faf3884 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs @@ -21,7 +21,7 @@ namespace MongoDB.Bson.Serialization.Conventions /// /// Represents a registry of conventions. /// - public static class ConventionRegistry + public static class ConventionRegistry //TODO Probably this should get the same treatment as BsonSerializer.... { // private static fields private readonly static List __conventionPacks = new List(); diff --git a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs index 81f31d14444..91f2f8f39b9 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs @@ -35,6 +35,8 @@ public void PostProcess(BsonClassMap classMap) { if (idMemberMap.IdGenerator == null) { + //TODO For this, we either add a new PostProcess method to the IPostProcessingConvention that takes the domain + //or we pass the domain to the BsonClassMap. The first probably makes more sense, but it's messier. var idGenerator = BsonSerializer.LookupIdGenerator(idMemberMap.MemberType); if (idGenerator != null) { diff --git a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs index 9a0a7683368..76a3675e5c9 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs @@ -135,7 +135,7 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } - actualType = BsonSerializer.LookupActualType(nominalType, discriminator); + actualType = BsonSerializer.LookupActualType(nominalType, discriminator); //TODO For this (and other discriminator conventions) we need to add methods to IDiscriminatorConvention to pass the domain } bsonReader.ReturnToBookmark(bookmark); return actualType; diff --git a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs index 923936d1508..c938dc1cfc0 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs @@ -38,7 +38,7 @@ public void Apply(BsonMemberMap memberMap) return; } - var defaultStringSerializer = BsonSerializer.LookupSerializer(typeof(string)); + var defaultStringSerializer = BsonSerializer.LookupSerializer(typeof(string)); //TODO For this we'd need to add a new Apply(memberMap, domain) method to IMemberMapConvention if (memberMap.GetSerializer() != defaultStringSerializer) { return; diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs b/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs index fd5998c93b3..6846529dffb 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs @@ -58,7 +58,7 @@ public static TValue Deserialize(this IBsonSerializer serializer public static IDiscriminatorConvention GetDiscriminatorConvention(this IBsonSerializer serializer) => serializer is IHasDiscriminatorConvention hasDiscriminatorConvention ? hasDiscriminatorConvention.DiscriminatorConvention - : BsonSerializer.LookupDiscriminatorConvention(serializer.ValueType); + : BsonSerializer.LookupDiscriminatorConvention(serializer.ValueType); //TODO We need another version of this with the domain as input /// /// Serializes a value. diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs index 2ba62a8294c..3513883475c 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs @@ -89,7 +89,7 @@ public bool GetDocumentId( if (bsonDocument.TryGetValue("_id", out idBsonValue)) { id = idBsonValue; - idGenerator = BsonSerializer.LookupIdGenerator(id.GetType()); + idGenerator = BsonSerializer.LookupIdGenerator(id.GetType()); //TODO For this we need add a new GetDocumentId to IBsonIdProvider if (idGenerator == null) { diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs index 96b708d8aa6..ff441a7c54e 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs @@ -59,6 +59,7 @@ public DictionarySerializerBase() /// The dictionary representation. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation) : this(dictionaryRepresentation, BsonSerializer.LookupSerializer(), BsonSerializer.LookupSerializer()) + //TODO We could keep this, and add a new constructor DictionarySerializerBase(dictionaryRepresentation, domain) { } @@ -387,6 +388,7 @@ public DictionarySerializerBase() /// The dictionary representation. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation) : this(dictionaryRepresentation, BsonSerializer.SerializerRegistry) + //TODO We could keep this, and add a new constructor DictionarySerializerBase(dictionaryRepresentation, domain) { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs index 87a6d67f057..7f22d2bd9d3 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs @@ -47,7 +47,7 @@ private static IBsonSerializer CreateInterfaceSerializer() var classMapType = classMapDefinition.MakeGenericType(typeof(TInterface)); var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); classMap.AutoMap(); - classMap.SetDiscriminatorConvention(BsonSerializer.LookupDiscriminatorConvention(typeof(TInterface))); + classMap.SetDiscriminatorConvention(BsonSerializer.LookupDiscriminatorConvention(typeof(TInterface))); //TODO This is only called by the constructor, we need a new one with the domain as input classMap.Freeze(); return new BsonClassMapSerializer(classMap); } @@ -97,7 +97,7 @@ public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorCo _interfaceType = typeof(TInterface); _discriminatorConvention = discriminatorConvention ?? interfaceSerializer.GetDiscriminatorConvention(); - _objectSerializer = BsonSerializer.LookupSerializer(); + _objectSerializer = BsonSerializer.LookupSerializer(); //TODO We need a new constructor, that takes the domain as input. if (_objectSerializer is ObjectSerializer standardObjectSerializer) { _objectSerializer = standardObjectSerializer.WithDiscriminatorConvention(_discriminatorConvention); diff --git a/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs index d020fd3895d..f85e7c2e17e 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs @@ -26,8 +26,8 @@ namespace MongoDB.Bson.Serialization.Serializers /// The dynamic type. public abstract class DynamicDocumentBaseSerializer : SerializerBase where T : class, IDynamicMetaObjectProvider { - // private static fields - private static readonly IBsonSerializer __objectSerializer = BsonSerializer.LookupSerializer(); + // private fields + private IBsonSerializer __objectSerializer; // constructors /// @@ -58,7 +58,7 @@ public override T Deserialize(BsonDeserializationContext context, BsonDeserializ while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { var name = bsonReader.ReadName(); - var value = __objectSerializer.Deserialize(dynamicContext); + var value = GetObjectSerializer(context.Domain).Deserialize(dynamicContext); SetValueForMember(document, name, value); } bsonReader.ReadEndDocument(); @@ -101,7 +101,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati if (TryGetValueForMember(value, memberName, out memberValue)) { bsonWriter.WriteName(memberName); - __objectSerializer.Serialize(dynamicContext, memberValue); + GetObjectSerializer(context.Domain).Serialize(dynamicContext, memberValue); } } bsonWriter.WriteEndDocument(); @@ -142,5 +142,11 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati /// The value. /// true if the member should be serialized; otherwise false. protected abstract bool TryGetValueForMember(T document, string memberName, out object value); + + //private methods + private IBsonSerializer GetObjectSerializer(IBsonSerializationDomain domain) + { + return __objectSerializer ??= domain.LookupSerializer(); + } } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs index 5d810b01861..ec137955da0 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs @@ -35,7 +35,7 @@ public abstract class EnumerableSerializerBase : SerializerBase, /// Initializes a new instance of the class. /// protected EnumerableSerializerBase() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } @@ -234,7 +234,7 @@ public abstract class EnumerableSerializerBase : SerializerBase class. /// protected EnumerableSerializerBase() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs index 7160bc11288..489dba1f6ba 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs @@ -29,14 +29,13 @@ namespace MongoDB.Bson.Serialization.Serializers public sealed class ExpandoObjectSerializer : DynamicDocumentBaseSerializer { // private fields - private readonly IBsonSerializer> _listSerializer; + private IBsonSerializer> _listSerializer; /// /// Initializes a new instance of the class. /// public ExpandoObjectSerializer() { - _listSerializer = BsonSerializer.LookupSerializer>(); } /// diff --git a/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs index a5ce3afa28d..23c70a55ab8 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs @@ -50,7 +50,7 @@ private static void EnsureTIEnumerableIsAnInterface() /// Initializes a new instance of the IEnumerableDeserializingAsCollectionSerializer class. /// public IEnumerableDeserializingAsCollectionSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs index 74f9c72ce95..3f405ccb287 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs @@ -52,7 +52,7 @@ public sealed class ImpliedImplementationInterfaceSerializer class. /// public ImpliedImplementationInterfaceSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs index ea1f59ac971..8cbf31b741d 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs @@ -66,7 +66,7 @@ public KeyValuePairSerializer() /// /// The representation. public KeyValuePairSerializer(BsonType representation) - : this(representation, BsonSerializer.SerializerRegistry) + : this(representation, BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs index 8740bdd3a9b..5b92708c65c 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs @@ -64,7 +64,7 @@ public sealed class NullableSerializer : /// Initializes a new instance of the class. /// public NullableSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs index a8ccf35277c..0cfbe5114b3 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs @@ -67,7 +67,7 @@ public sealed class ObjectSerializer : ClassSerializerBase, IHasDiscrimi /// Initializes a new instance of the class. /// public ObjectSerializer() - : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object))) + : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object))) //TODO Need a new constructor that takes the domain as input { } @@ -96,7 +96,7 @@ public ObjectSerializer(IDiscriminatorConvention discriminatorConvention, GuidRe /// /// A delegate that determines what types are allowed. public ObjectSerializer(Func allowedTypes) - : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object)), allowedTypes) + : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object)), allowedTypes) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs index 065ae3873f9..d2b8868a992 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs @@ -32,7 +32,7 @@ public sealed class SerializeAsNominalTypeSerializer /// Initializes a new instance of the class. /// public SerializeAsNominalTypeSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs index c2aaf3998fb..b5063d2d5d3 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs @@ -34,7 +34,7 @@ public sealed class ThreeDimensionalArraySerializer : /// Initializes a new instance of the class. /// public ThreeDimensionalArraySerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs b/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs index a5b1e5f290a..1c6870544d8 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs @@ -114,7 +114,7 @@ public sealed class TupleSerializer : SealedClassSerializerBase>, /// Initializes a new instance of the class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input (also for all the other constructors in here) { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs index afe701dd1c3..ff0d4370de0 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs @@ -34,7 +34,7 @@ public sealed class TwoDimensionalArraySerializer : /// Initializes a new instance of the class. /// public TwoDimensionalArraySerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs b/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs index d0f52484e58..9003a83b0cd 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs @@ -75,7 +75,7 @@ public sealed class ValueTupleSerializer : StructSerializerBase class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input { } From 3dadb0750bfba330d5007e87a18bcae7f15fb1e2 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 15 Jan 2025 11:34:15 +0100 Subject: [PATCH 13/49] Test with multiple interfaces --- .../Serialization/IBsonSerializationDomain.cs | 217 ++++++++++-------- 1 file changed, 115 insertions(+), 102 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index ac0f790e70a..dcb27a1d981 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -6,26 +6,84 @@ namespace MongoDB.Bson.Serialization { + /// /// //TODO /// - public interface IBsonSerializationDomain + public interface ISerializerConfigurator { /// - /// Gets the serializer registry. + /// Registers the discriminator for a type. /// - IBsonSerializerRegistry SerializerRegistry { get; } + /// The type. + /// The discriminator. + void RegisterDiscriminator(Type type, BsonValue discriminator); /// - /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// Registers the discriminator convention for a type. /// - bool UseNullIdChecker { get; set; } + /// Type type. + /// The discriminator convention. + void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); /// - /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// Registers a generic serializer definition for a generic type. /// - bool UseZeroIdChecker { get; set; } + /// The generic type. + /// The generic serializer definition. + void RegisterGenericSerializerDefinition( + Type genericTypeDefinition, + Type genericSerializerDefinition); + + /// + /// Registers an IdGenerator for an Id Type. + /// + /// The Id Type. + /// The IdGenerator for the Id Type. + void RegisterIdGenerator(Type type, IIdGenerator idGenerator); + + /// + /// Registers a serialization provider. + /// + /// The serialization provider. + void RegisterSerializationProvider(IBsonSerializationProvider provider); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(IBsonSerializer serializer); + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Tries to register a serializer for a type. + /// + /// The serializer. + /// The type. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Tries to register a serializer for a type. + /// + /// The type. + /// The serializer. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(IBsonSerializer serializer); + } + + /// + /// //TODO + /// + public interface IMainSerializer + { /// /// Deserializes an object from a BsonDocument. /// @@ -146,6 +204,56 @@ object Deserialize(string json, Type nominalType, object Deserialize(TextReader textReader, Type nominalType, Action configurator = null); + /// + /// Serializes a value. + /// + /// The nominal type of the object. + /// The BsonWriter. + /// The object. + /// The serialization context configurator. + /// The serialization args. + void Serialize( + IBsonWriter bsonWriter, + TNominalType value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)); + + /// + /// Serializes a value. + /// + /// The BsonWriter. + /// The nominal type of the object. + /// The object. + /// The serialization context configurator. + /// The serialization args. + void Serialize( + IBsonWriter bsonWriter, + Type nominalType, + object value, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)); + } + + /// + /// //TODO + /// + public interface IBsonSerializationDomain : ISerializerConfigurator, IMainSerializer + { + /// + /// Gets the serializer registry. + /// + IBsonSerializerRegistry SerializerRegistry { get; } + + /// + /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// + bool UseNullIdChecker { get; set; } + + /// + /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// + bool UseZeroIdChecker { get; set; } + /// /// Returns whether the given type has any discriminators registered for any of its subclasses. /// @@ -188,101 +296,6 @@ object Deserialize(TextReader textReader, Type nominalType, /// The Type. /// A serializer for the Type. IBsonSerializer LookupSerializer(Type type); - - /// - /// Registers the discriminator for a type. - /// - /// The type. - /// The discriminator. - void RegisterDiscriminator(Type type, BsonValue discriminator); - - /// - /// Registers the discriminator convention for a type. - /// - /// Type type. - /// The discriminator convention. - void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); - - /// - /// Registers a generic serializer definition for a generic type. - /// - /// The generic type. - /// The generic serializer definition. - void RegisterGenericSerializerDefinition( - Type genericTypeDefinition, - Type genericSerializerDefinition); - - /// - /// Registers an IdGenerator for an Id Type. - /// - /// The Id Type. - /// The IdGenerator for the Id Type. - void RegisterIdGenerator(Type type, IIdGenerator idGenerator); - - /// - /// Registers a serialization provider. - /// - /// The serialization provider. - void RegisterSerializationProvider(IBsonSerializationProvider provider); - - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(IBsonSerializer serializer); - - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(Type type, IBsonSerializer serializer); - - /// - /// Serializes a value. - /// - /// The nominal type of the object. - /// The BsonWriter. - /// The object. - /// The serialization context configurator. - /// The serialization args. - void Serialize( - IBsonWriter bsonWriter, - TNominalType value, - Action configurator = null, - BsonSerializationArgs args = default(BsonSerializationArgs)); - - /// - /// Serializes a value. - /// - /// The BsonWriter. - /// The nominal type of the object. - /// The object. - /// The serialization context configurator. - /// The serialization args. - void Serialize( - IBsonWriter bsonWriter, - Type nominalType, - object value, - Action configurator = null, - BsonSerializationArgs args = default(BsonSerializationArgs)); - - /// - /// Tries to register a serializer for a type. - /// - /// The serializer. - /// The type. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(Type type, IBsonSerializer serializer); - - /// - /// Tries to register a serializer for a type. - /// - /// The type. - /// The serializer. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(IBsonSerializer serializer); } internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain From cf05d41719dc0b00adcfc86bac3a2d8bef83db58 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 15 Jan 2025 13:03:16 +0100 Subject: [PATCH 14/49] Improved interfaces --- .../Serialization/BsonClassMap.cs | 2 +- .../Serialization/IBsonSerializationDomain.cs | 43 +++++++++++-------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 07035df3719..5bb56d12315 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -375,7 +375,7 @@ public static BsonClassMap LookupClassMap(Type classType) /// /// The class. /// The class map. - public static BsonClassMap RegisterClassMap() + public static BsonClassMap RegisterClassMap() //TODO We should move the static methods here to IBSonSerializerDomain { return RegisterClassMap(cm => { cm.AutoMap(); }); } diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index dcb27a1d981..16b9ff93c9a 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -10,7 +10,7 @@ namespace MongoDB.Bson.Serialization /// /// //TODO /// - public interface ISerializerConfigurator + public interface IBsonSerializationConfigurator { /// /// Registers the discriminator for a type. @@ -77,12 +77,23 @@ void RegisterGenericSerializerDefinition( /// The serializer. /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. bool TryRegisterSerializer(IBsonSerializer serializer); + + /// + /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// + bool UseNullIdChecker { get; set; } //TODO This should become a getter only property and a method + + /// + /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// + bool UseZeroIdChecker { get; set; } + } /// /// //TODO /// - public interface IMainSerializer + public interface IBsonCoreSerializer //TODO Don't like the name but have no better idea at the moment { /// /// Deserializes an object from a BsonDocument. @@ -237,23 +248,8 @@ void Serialize( /// /// //TODO /// - public interface IBsonSerializationDomain : ISerializerConfigurator, IMainSerializer + public interface IBsonSerializationConfiguration { - /// - /// Gets the serializer registry. - /// - IBsonSerializerRegistry SerializerRegistry { get; } - - /// - /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. - /// - bool UseNullIdChecker { get; set; } - - /// - /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. - /// - bool UseZeroIdChecker { get; set; } - /// /// Returns whether the given type has any discriminators registered for any of its subclasses. /// @@ -298,6 +294,17 @@ public interface IBsonSerializationDomain : ISerializerConfigurator, IMainSerial IBsonSerializer LookupSerializer(Type type); } + /// + /// //TODO + /// + public interface IBsonSerializationDomain : IBsonSerializationConfigurator, IBsonSerializationConfiguration, IBsonCoreSerializer + { + /// + /// Gets the serializer registry. + /// + IBsonSerializerRegistry SerializerRegistry { get; } + } + internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain { ReaderWriterLockSlim ConfigLock { get; } From 35f461a97b471680d844efd3d82ae5577b6198c7 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 15 Jan 2025 13:31:15 +0100 Subject: [PATCH 15/49] Fix to interface --- .../Serialization/BsonSerializationDomain.cs | 12 +++++++ .../Serialization/IBsonSerializationDomain.cs | 31 ++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 5076bc42d9e..44fa97889c0 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -66,6 +66,8 @@ public bool UseNullIdChecker set { __useNullIdChecker = value; } } + public bool UseNullIdCheckerEnabled => UseNullIdChecker; + /// /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. /// @@ -75,13 +77,23 @@ public bool UseZeroIdChecker set { __useZeroIdChecker = value; } } + public bool UseZeroIdCheckerEnabled => UseZeroIdChecker; + // internal properties public ReaderWriterLockSlim ConfigLock { get { return __configLock; } } + public IBsonSerializationConfiguration SerializationConfiguration => this; + // public methods + + public IBsonCoreSerializer BuildCoreSerializer() + { + return this; + } + /// /// Deserializes an object from a BsonDocument. /// diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index 16b9ff93c9a..fcdfab4c894 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -81,13 +81,18 @@ void RegisterGenericSerializerDefinition( /// /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. /// - bool UseNullIdChecker { get; set; } //TODO This should become a getter only property and a method + bool UseNullIdChecker { get; set; } //TODO It would be nice if this became a method (SetUseNullIdChecker) and the configuration would have only a getter /// /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. /// bool UseZeroIdChecker { get; set; } + /// + /// //TODO + /// + /// + IBsonCoreSerializer BuildCoreSerializer(); } /// @@ -95,6 +100,11 @@ void RegisterGenericSerializerDefinition( /// public interface IBsonCoreSerializer //TODO Don't like the name but have no better idea at the moment { + /// + /// //TODO + /// + IBsonSerializationConfiguration SerializationConfiguration { get; } + /// /// Deserializes an object from a BsonDocument. /// @@ -292,6 +302,21 @@ public interface IBsonSerializationConfiguration /// The Type. /// A serializer for the Type. IBsonSerializer LookupSerializer(Type type); + + /// + /// Gets the serializer registry. + /// + IBsonSerializerRegistry SerializerRegistry { get; } + + /// + /// Gets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered is enabled. + /// + bool UseNullIdCheckerEnabled { get; } + + /// + /// Gets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered is enabled. + /// + bool UseZeroIdCheckerEnabled { get; } } /// @@ -299,10 +324,6 @@ public interface IBsonSerializationConfiguration /// public interface IBsonSerializationDomain : IBsonSerializationConfigurator, IBsonSerializationConfiguration, IBsonCoreSerializer { - /// - /// Gets the serializer registry. - /// - IBsonSerializerRegistry SerializerRegistry { get; } } internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain From 7c2beb359f141f4a8c4f2814e1dbb0eeec39517d Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:29:34 +0100 Subject: [PATCH 16/49] Small renaming --- .../Serialization/BsonSerializationDomain.cs | 2 +- .../Serialization/IBsonSerializationDomain.cs | 199 +++++++++--------- 2 files changed, 100 insertions(+), 101 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 44fa97889c0..cba4f3d2b84 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -85,7 +85,7 @@ public ReaderWriterLockSlim ConfigLock get { return __configLock; } } - public IBsonSerializationConfiguration SerializationConfiguration => this; + public IBsonCoreSerializerConfiguration SerializationConfiguration => this; // public methods diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index fcdfab4c894..9c1a3be8977 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -6,93 +6,23 @@ namespace MongoDB.Bson.Serialization { - /// /// //TODO /// - public interface IBsonSerializationConfigurator + public interface IBsonSerializationDomain : IBsonCoreSerializerConfigurator, IBsonCoreSerializerConfiguration, IBsonCoreSerializer { - /// - /// Registers the discriminator for a type. - /// - /// The type. - /// The discriminator. - void RegisterDiscriminator(Type type, BsonValue discriminator); - - /// - /// Registers the discriminator convention for a type. - /// - /// Type type. - /// The discriminator convention. - void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); - - /// - /// Registers a generic serializer definition for a generic type. - /// - /// The generic type. - /// The generic serializer definition. - void RegisterGenericSerializerDefinition( - Type genericTypeDefinition, - Type genericSerializerDefinition); - - /// - /// Registers an IdGenerator for an Id Type. - /// - /// The Id Type. - /// The IdGenerator for the Id Type. - void RegisterIdGenerator(Type type, IIdGenerator idGenerator); - - /// - /// Registers a serialization provider. - /// - /// The serialization provider. - void RegisterSerializationProvider(IBsonSerializationProvider provider); - - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(IBsonSerializer serializer); - - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(Type type, IBsonSerializer serializer); - - /// - /// Tries to register a serializer for a type. - /// - /// The serializer. - /// The type. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(Type type, IBsonSerializer serializer); + } - /// - /// Tries to register a serializer for a type. - /// - /// The type. - /// The serializer. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(IBsonSerializer serializer); + internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain + { + ReaderWriterLockSlim ConfigLock { get; } - /// - /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. - /// - bool UseNullIdChecker { get; set; } //TODO It would be nice if this became a method (SetUseNullIdChecker) and the configuration would have only a getter + void EnsureKnownTypesAreRegistered(Type nominalType); - /// - /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. - /// - bool UseZeroIdChecker { get; set; } + IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, + IDiscriminatorConvention discriminatorConvention); - /// - /// //TODO - /// - /// - IBsonCoreSerializer BuildCoreSerializer(); + bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type); } /// @@ -103,7 +33,7 @@ public interface IBsonCoreSerializer //TODO Don't like the name but have no bett /// /// //TODO /// - IBsonSerializationConfiguration SerializationConfiguration { get; } + IBsonCoreSerializerConfiguration SerializationConfiguration { get; } /// /// Deserializes an object from a BsonDocument. @@ -258,7 +188,95 @@ void Serialize( /// /// //TODO /// - public interface IBsonSerializationConfiguration + public interface IBsonCoreSerializerConfigurator + { + /// + /// Registers the discriminator for a type. + /// + /// The type. + /// The discriminator. + void RegisterDiscriminator(Type type, BsonValue discriminator); + + /// + /// Registers the discriminator convention for a type. + /// + /// Type type. + /// The discriminator convention. + void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); + + /// + /// Registers a generic serializer definition for a generic type. + /// + /// The generic type. + /// The generic serializer definition. + void RegisterGenericSerializerDefinition( + Type genericTypeDefinition, + Type genericSerializerDefinition); + + /// + /// Registers an IdGenerator for an Id Type. + /// + /// The Id Type. + /// The IdGenerator for the Id Type. + void RegisterIdGenerator(Type type, IIdGenerator idGenerator); + + /// + /// Registers a serialization provider. + /// + /// The serialization provider. + void RegisterSerializationProvider(IBsonSerializationProvider provider); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(IBsonSerializer serializer); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Tries to register a serializer for a type. + /// + /// The serializer. + /// The type. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Tries to register a serializer for a type. + /// + /// The type. + /// The serializer. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(IBsonSerializer serializer); + + /// + /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// + bool UseNullIdChecker { get; set; } //TODO It would be nice if this became a method (SetUseNullIdChecker) and the configuration would have only a getter + + /// + /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// + bool UseZeroIdChecker { get; set; } + + /// + /// //TODO + /// + /// + IBsonCoreSerializer BuildCoreSerializer(); + } + + /// + /// //TODO + /// + public interface IBsonCoreSerializerConfiguration { /// /// Returns whether the given type has any discriminators registered for any of its subclasses. @@ -318,23 +336,4 @@ public interface IBsonSerializationConfiguration /// bool UseZeroIdCheckerEnabled { get; } } - - /// - /// //TODO - /// - public interface IBsonSerializationDomain : IBsonSerializationConfigurator, IBsonSerializationConfiguration, IBsonCoreSerializer - { - } - - internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain - { - ReaderWriterLockSlim ConfigLock { get; } - - void EnsureKnownTypesAreRegistered(Type nominalType); - - IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, - IDiscriminatorConvention discriminatorConvention); - - bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type); - } } \ No newline at end of file From 3ad811ea566d9557bb9dc836cb84708a5692a477 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:48:29 +0100 Subject: [PATCH 17/49] Added comments --- .../Serializers/BsonDocumentSerializer.cs | 2 +- .../Serializers/DictionarySerializerBase.cs | 6 ++---- .../DiscriminatedInterfaceSerializer.cs | 4 ++-- .../Serializers/EnumerableSerializerBase.cs | 4 ++-- ...merableDeserializingAsCollectionSerializer.cs | 2 +- .../ImpliedImplementationInterfaceSerializer.cs | 2 +- .../Serializers/KeyValuePairSerializer.cs | 2 +- .../Serializers/NullableSerializer.cs | 2 +- .../Serializers/ObjectSerializer.cs | 4 ++-- .../SerializeAsNominalTypeSerializer.cs | 2 +- .../ThreeDimensionalArraySerializer.cs | 2 +- .../Serializers/TupleSerializers.cs | 16 ++++++++-------- .../Serializers/TwoDimensionalArraySerializer.cs | 2 +- .../Serializers/ValueTupleSerializers.cs | 16 ++++++++-------- 14 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs index 3513883475c..0091c927ffe 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs @@ -89,7 +89,7 @@ public bool GetDocumentId( if (bsonDocument.TryGetValue("_id", out idBsonValue)) { id = idBsonValue; - idGenerator = BsonSerializer.LookupIdGenerator(id.GetType()); //TODO For this we need add a new GetDocumentId to IBsonIdProvider + idGenerator = BsonSerializer.LookupIdGenerator(id.GetType()); //TODO ?? if (idGenerator == null) { diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs index ff441a7c54e..3ae2562a928 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DictionarySerializerBase.cs @@ -58,8 +58,7 @@ public DictionarySerializerBase() /// /// The dictionary representation. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation) - : this(dictionaryRepresentation, BsonSerializer.LookupSerializer(), BsonSerializer.LookupSerializer()) - //TODO We could keep this, and add a new constructor DictionarySerializerBase(dictionaryRepresentation, domain) + : this(dictionaryRepresentation, BsonSerializer.LookupSerializer(), BsonSerializer.LookupSerializer()) //TODO We can keep this as is { } @@ -387,8 +386,7 @@ public DictionarySerializerBase() /// /// The dictionary representation. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation) - : this(dictionaryRepresentation, BsonSerializer.SerializerRegistry) - //TODO We could keep this, and add a new constructor DictionarySerializerBase(dictionaryRepresentation, domain) + : this(dictionaryRepresentation, BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs index 7f22d2bd9d3..a5334d85e76 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs @@ -47,7 +47,7 @@ private static IBsonSerializer CreateInterfaceSerializer() var classMapType = classMapDefinition.MakeGenericType(typeof(TInterface)); var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); classMap.AutoMap(); - classMap.SetDiscriminatorConvention(BsonSerializer.LookupDiscriminatorConvention(typeof(TInterface))); //TODO This is only called by the constructor, we need a new one with the domain as input + classMap.SetDiscriminatorConvention(BsonSerializer.LookupDiscriminatorConvention(typeof(TInterface))); //TODO ?? classMap.Freeze(); return new BsonClassMapSerializer(classMap); } @@ -97,7 +97,7 @@ public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorCo _interfaceType = typeof(TInterface); _discriminatorConvention = discriminatorConvention ?? interfaceSerializer.GetDiscriminatorConvention(); - _objectSerializer = BsonSerializer.LookupSerializer(); //TODO We need a new constructor, that takes the domain as input. + _objectSerializer = BsonSerializer.LookupSerializer(); //TODO ?? if (_objectSerializer is ObjectSerializer standardObjectSerializer) { _objectSerializer = standardObjectSerializer.WithDiscriminatorConvention(_discriminatorConvention); diff --git a/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs index ec137955da0..32bc8a95663 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/EnumerableSerializerBase.cs @@ -35,7 +35,7 @@ public abstract class EnumerableSerializerBase : SerializerBase, /// Initializes a new instance of the class. /// protected EnumerableSerializerBase() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -234,7 +234,7 @@ public abstract class EnumerableSerializerBase : SerializerBase class. /// protected EnumerableSerializerBase() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs index 23c70a55ab8..e7f705259a6 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/IEnumerableDeserializingAsCollectionSerializer.cs @@ -50,7 +50,7 @@ private static void EnsureTIEnumerableIsAnInterface() /// Initializes a new instance of the IEnumerableDeserializingAsCollectionSerializer class. /// public IEnumerableDeserializingAsCollectionSerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs index 3f405ccb287..fc128f6e17b 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs @@ -52,7 +52,7 @@ public sealed class ImpliedImplementationInterfaceSerializer class. /// public ImpliedImplementationInterfaceSerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs index 8cbf31b741d..9f9ccb66051 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/KeyValuePairSerializer.cs @@ -66,7 +66,7 @@ public KeyValuePairSerializer() /// /// The representation. public KeyValuePairSerializer(BsonType representation) - : this(representation, BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(representation, BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs index 5b92708c65c..f55c2dd9e06 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/NullableSerializer.cs @@ -64,7 +64,7 @@ public sealed class NullableSerializer : /// Initializes a new instance of the class. /// public NullableSerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs index 0cfbe5114b3..e1416c7cd50 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs @@ -67,7 +67,7 @@ public sealed class ObjectSerializer : ClassSerializerBase, IHasDiscrimi /// Initializes a new instance of the class. /// public ObjectSerializer() - : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object))) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object))) //TODO We can keep this as is { } @@ -96,7 +96,7 @@ public ObjectSerializer(IDiscriminatorConvention discriminatorConvention, GuidRe /// /// A delegate that determines what types are allowed. public ObjectSerializer(Func allowedTypes) - : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object)), allowedTypes) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.LookupDiscriminatorConvention(typeof(object)), allowedTypes) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs index d2b8868a992..068496a8ad0 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/SerializeAsNominalTypeSerializer.cs @@ -32,7 +32,7 @@ public sealed class SerializeAsNominalTypeSerializer /// Initializes a new instance of the class. /// public SerializeAsNominalTypeSerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs index b5063d2d5d3..96c2221e071 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ThreeDimensionalArraySerializer.cs @@ -34,7 +34,7 @@ public sealed class ThreeDimensionalArraySerializer : /// Initializes a new instance of the class. /// public ThreeDimensionalArraySerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs b/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs index 1c6870544d8..140f40c9259 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/TupleSerializers.cs @@ -114,7 +114,7 @@ public sealed class TupleSerializer : SealedClassSerializerBase>, /// Initializes a new instance of the class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input (also for all the other constructors in here) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -208,7 +208,7 @@ public sealed class TupleSerializer : SealedClassSerializerBase class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -318,7 +318,7 @@ public sealed class TupleSerializer : SealedClassSerializerBase class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -443,7 +443,7 @@ public sealed class TupleSerializer : SealedClassSerializerBase< /// Initializes a new instance of the class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -585,7 +585,7 @@ public sealed class TupleSerializer : SealedClassSerializerB /// Initializes a new instance of the class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -743,7 +743,7 @@ public sealed class TupleSerializer : SealedClassSeriali /// Initializes a new instance of the class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -917,7 +917,7 @@ public sealed class TupleSerializer : SealedClassSer /// Initializes a new instance of the class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -1107,7 +1107,7 @@ public sealed class TupleSerializer : SealedC /// Initializes a new instance of the class. /// public TupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs index ff0d4370de0..a23618a0780 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/TwoDimensionalArraySerializer.cs @@ -34,7 +34,7 @@ public sealed class TwoDimensionalArraySerializer : /// Initializes a new instance of the class. /// public TwoDimensionalArraySerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs b/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs index 9003a83b0cd..ba90fc15104 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ValueTupleSerializers.cs @@ -75,7 +75,7 @@ public sealed class ValueTupleSerializer : StructSerializerBase class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) //TODO Need a new constructor that takes the domain as input + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -193,7 +193,7 @@ public sealed class ValueTupleSerializer : StructSerializerBase class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -329,7 +329,7 @@ public sealed class ValueTupleSerializer : StructSerializerBase class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -483,7 +483,7 @@ public sealed class ValueTupleSerializer : StructSerializerBase< /// Initializes a new instance of the class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -655,7 +655,7 @@ public sealed class ValueTupleSerializer : StructSerializerB /// Initializes a new instance of the class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -845,7 +845,7 @@ public sealed class ValueTupleSerializer : StructSeriali /// Initializes a new instance of the class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -1053,7 +1053,7 @@ public sealed class ValueTupleSerializer : StructSer /// Initializes a new instance of the class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } @@ -1280,7 +1280,7 @@ public sealed class ValueTupleSerializer : St /// Initializes a new instance of the class. /// public ValueTupleSerializer() - : this(BsonSerializer.SerializerRegistry) + : this(BsonSerializer.SerializerRegistry) //TODO We can keep this as is { } From 0ae768c2a92abca70d6b2ea810012844a2e911d5 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:54:10 +0100 Subject: [PATCH 18/49] Finished comments in the Bson lib --- src/MongoDB.Bson/BsonDefaults.cs | 4 ++-- src/MongoDB.Bson/BsonExtensionMethods.cs | 6 +++--- src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs | 6 +++--- src/MongoDB.Bson/Serialization/BsonMemberMap.cs | 4 ++-- .../Serialization/BsonSerializationProviderBase.cs | 6 +++--- .../Conventions/LookupIdGeneratorConvention.cs | 3 +-- .../Conventions/ObjectDiscriminatorConvention.cs | 2 +- .../Conventions/StandardDiscriminatorConvention.cs | 6 +++--- .../Conventions/StringIdStoredAsObjectIdConvention.cs | 2 +- src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs | 2 +- 10 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/MongoDB.Bson/BsonDefaults.cs b/src/MongoDB.Bson/BsonDefaults.cs index 32239ec64a3..70bfd775056 100644 --- a/src/MongoDB.Bson/BsonDefaults.cs +++ b/src/MongoDB.Bson/BsonDefaults.cs @@ -42,7 +42,7 @@ public static IBsonSerializer DynamicArraySerializer { if (!__dynamicArraySerializerWasSet) { - __dynamicArraySerializer = BsonSerializer.LookupSerializer>(); //TODO I think we could keep this as is + __dynamicArraySerializer = BsonSerializer.LookupSerializer>(); //TODO ?? } return __dynamicArraySerializer; } @@ -62,7 +62,7 @@ public static IBsonSerializer DynamicDocumentSerializer { if (!__dynamicDocumentSerializerWasSet) { - __dynamicDocumentSerializer = BsonSerializer.LookupSerializer(); //TODO I think we could keep this as is + __dynamicDocumentSerializer = BsonSerializer.LookupSerializer(); //TODO ?? } return __dynamicDocumentSerializer; } diff --git a/src/MongoDB.Bson/BsonExtensionMethods.cs b/src/MongoDB.Bson/BsonExtensionMethods.cs index c885a81b834..6494a4c4b1c 100644 --- a/src/MongoDB.Bson/BsonExtensionMethods.cs +++ b/src/MongoDB.Bson/BsonExtensionMethods.cs @@ -84,7 +84,7 @@ public static byte[] ToBson( if (serializer == null) { - serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think we need another method with the domain as input + serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? } if (serializer.ValueType != nominalType) { @@ -165,7 +165,7 @@ public static BsonDocument ToBsonDocument( return convertibleToBsonDocument.ToBsonDocument(); // use the provided ToBsonDocument method } - serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think we need another method with the domain as input + serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? } if (serializer.ValueType != nominalType) { @@ -236,7 +236,7 @@ public static string ToJson( if (serializer == null) { - serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think we need another method with the domain as input + serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? } if (serializer.ValueType != nominalType) { diff --git a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs index 12feae4a013..1a19e75c857 100644 --- a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs +++ b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs @@ -104,7 +104,7 @@ public static BsonDocumentWrapper Create(TNominalType value) /// A BsonDocumentWrapper. public static BsonDocumentWrapper Create(Type nominalType, object value) { - var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think this could stay. We can potentially add methods with the domain as input. + var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? return new BsonDocumentWrapper(value, serializer); } @@ -121,7 +121,7 @@ public static IEnumerable CreateMultiple(IEnu throw new ArgumentNullException("values"); } - var serializer = BsonSerializer.LookupSerializer(typeof(TNominalType)); //TODO I think this could stay. We can potentially add methods with the domain as input. + var serializer = BsonSerializer.LookupSerializer(typeof(TNominalType)); //TODO ?? return values.Select(v => new BsonDocumentWrapper(v, serializer)); } @@ -142,7 +142,7 @@ public static IEnumerable CreateMultiple(Type nominalType, throw new ArgumentNullException("values"); } - var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO I think this could stay. We can potentially add methods with the domain as input. + var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? return values.Cast().Select(v => new BsonDocumentWrapper(v, serializer)); } diff --git a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs index 630e0834546..98bdbbe4aab 100644 --- a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs @@ -301,7 +301,7 @@ public IBsonSerializer GetSerializer() // return special serializer for BsonValue members that handles the _csharpnull representation if (_memberTypeIsBsonValue) { - var wrappedSerializer = BsonSerializer.LookupSerializer(_memberType); //TODO We need another version of this with the domain as input + var wrappedSerializer = BsonSerializer.LookupSerializer(_memberType); //TODO ?? var isBsonArraySerializer = wrappedSerializer is IBsonArraySerializer; var isBsonDocumentSerializer = wrappedSerializer is IBsonDocumentSerializer; @@ -329,7 +329,7 @@ public IBsonSerializer GetSerializer() } else { - _serializer = BsonSerializer.LookupSerializer(_memberType); + _serializer = BsonSerializer.LookupSerializer(_memberType); //TODO ?? } } return _serializer; diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs b/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs index 0f3645ac2fe..93195b5b773 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs @@ -24,7 +24,7 @@ namespace MongoDB.Bson.Serialization public abstract class BsonSerializationProviderBase : IRegistryAwareBsonSerializationProvider { /// - public virtual IBsonSerializer GetSerializer(Type type) //TODO Need to make another version with the domain as input + public virtual IBsonSerializer GetSerializer(Type type) //TODO We can keep this as is { return GetSerializer(type, BsonSerializer.SerializerRegistry); } @@ -38,7 +38,7 @@ public virtual IBsonSerializer GetSerializer(Type type) //TODO Need to make ano /// The serializer type definition. /// The type arguments. /// A serializer. - protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDefinition, params Type[] typeArguments) //TODO We need another version of this with the domain as input + protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDefinition, params Type[] typeArguments) //TODO We can keep this as is { return CreateGenericSerializer(serializerTypeDefinition, typeArguments, BsonSerializer.SerializerRegistry); } @@ -65,7 +65,7 @@ protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDef /// A serializer. protected virtual IBsonSerializer CreateSerializer(Type serializerType) { - return CreateSerializer(serializerType, BsonSerializer.SerializerRegistry); //TODO We need another version of this with the domain as input + return CreateSerializer(serializerType, BsonSerializer.SerializerRegistry); //TODO We can keep this as is } /// diff --git a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs index 91f2f8f39b9..fa69c69c99b 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs @@ -35,9 +35,8 @@ public void PostProcess(BsonClassMap classMap) { if (idMemberMap.IdGenerator == null) { - //TODO For this, we either add a new PostProcess method to the IPostProcessingConvention that takes the domain //or we pass the domain to the BsonClassMap. The first probably makes more sense, but it's messier. - var idGenerator = BsonSerializer.LookupIdGenerator(idMemberMap.MemberType); + var idGenerator = BsonSerializer.LookupIdGenerator(idMemberMap.MemberType); //TODO ?? if (idGenerator != null) { idMemberMap.SetIdGenerator(idGenerator); diff --git a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs index 76a3675e5c9..34ad86da3c5 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs @@ -135,7 +135,7 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } - actualType = BsonSerializer.LookupActualType(nominalType, discriminator); //TODO For this (and other discriminator conventions) we need to add methods to IDiscriminatorConvention to pass the domain + actualType = BsonSerializer.LookupActualType(nominalType, discriminator); //TODO ?? } bsonReader.ReturnToBookmark(bookmark); return actualType; diff --git a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs index ca4d2cbc117..b1664389282 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs @@ -101,10 +101,10 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) if (bsonType == BsonType.Document) { // ensure KnownTypes of nominalType are registered (so IsTypeDiscriminated returns correct answer) - BsonSerializer.EnsureKnownTypesAreRegistered(nominalType); + BsonSerializer.EnsureKnownTypesAreRegistered(nominalType); //TODO ?? // we can skip looking for a discriminator if nominalType has no discriminated sub types - if (BsonSerializer.IsTypeDiscriminated(nominalType)) + if (BsonSerializer.IsTypeDiscriminated(nominalType)) //TODO ?? { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); @@ -117,7 +117,7 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } - actualType = BsonSerializer.LookupActualType(nominalType, discriminator); + actualType = BsonSerializer.LookupActualType(nominalType, discriminator); //TODO ?? } bsonReader.ReturnToBookmark(bookmark); return actualType; diff --git a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs index c938dc1cfc0..ffa79944dd1 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs @@ -38,7 +38,7 @@ public void Apply(BsonMemberMap memberMap) return; } - var defaultStringSerializer = BsonSerializer.LookupSerializer(typeof(string)); //TODO For this we'd need to add a new Apply(memberMap, domain) method to IMemberMapConvention + var defaultStringSerializer = BsonSerializer.LookupSerializer(typeof(string)); //TODO ?? if (memberMap.GetSerializer() != defaultStringSerializer) { return; diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs b/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs index 6846529dffb..18ef341df5d 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs @@ -58,7 +58,7 @@ public static TValue Deserialize(this IBsonSerializer serializer public static IDiscriminatorConvention GetDiscriminatorConvention(this IBsonSerializer serializer) => serializer is IHasDiscriminatorConvention hasDiscriminatorConvention ? hasDiscriminatorConvention.DiscriminatorConvention - : BsonSerializer.LookupDiscriminatorConvention(serializer.ValueType); //TODO We need another version of this with the domain as input + : BsonSerializer.LookupDiscriminatorConvention(serializer.ValueType); //TODO We can keep this as is /// /// Serializes a value. From 01330fd5a7af29a3a6ca7209cfc06be3f8bb95b0 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:34:32 +0100 Subject: [PATCH 19/49] Corrected conventions --- .../Conventions/AttributeConventionPack.cs | 8 ++++++-- .../Conventions/CamelCaseElementNameConvention.cs | 10 +++++----- .../Conventions/DelegateMemberMapConvention.cs | 5 ++++- .../Conventions/DelegatePostProcessingConvention.cs | 5 ++++- .../Conventions/EnumRepresentationConvention.cs | 5 ++++- .../Conventions/IMemberMapConvention.cs | 8 ++++++++ .../Conventions/IPostProcessingConvention.cs | 7 +++++++ .../Conventions/IgnoreIfDefaultConvention.cs | 5 ++++- .../Conventions/IgnoreIfNullConvention.cs | 5 ++++- .../Conventions/LookupIdGeneratorConvention.cs | 13 ++++++------- .../Conventions/MemberDefaultValueConvention.cs | 5 ++++- .../Conventions/MemberNameElementNameConvention.cs | 5 ++++- .../Conventions/NoIdMemberConvention.cs | 5 ++++- .../ObjectSerializerAllowedTypesConvention.cs | 5 ++++- .../Conventions/ResetMemberMapsConvention.cs | 5 ++++- .../StringIdStoredAsObjectIdConvention.cs | 7 +++++-- .../StringObjectIdIdGeneratorConvention.cs | 5 ++++- 17 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs b/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs index 77f0bc0cb78..13334d0280b 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs @@ -87,7 +87,9 @@ public void Apply(BsonCreatorMap creatorMap) } } - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { var attributes = memberMap.MemberInfo.GetCustomAttributes(inherit: false).OfType(); var groupings = attributes.GroupBy(a => (a is BsonSerializerAttribute) ? 1 : 2); @@ -100,7 +102,9 @@ public void Apply(BsonMemberMap memberMap) } } - public void PostProcess(BsonClassMap classMap) + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + + public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) { foreach (var attribute in classMap.ClassType.GetTypeInfo().GetCustomAttributes(inherit: false).OfType()) { diff --git a/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs index dd249c11359..7db675337ca 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs @@ -24,11 +24,11 @@ namespace MongoDB.Bson.Serialization.Conventions public class CamelCaseElementNameConvention : ConventionBase, IMemberMapConvention { // public methods - /// - /// Applies a modification to the member map. - /// - /// The member map. - public void Apply(BsonMemberMap memberMap) + /// + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { string name = memberMap.MemberName; name = GetElementName(name); diff --git a/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs index 80cafe70046..f2b46569615 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs @@ -46,7 +46,10 @@ public DelegateMemberMapConvention(string name, Action action) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { _action(memberMap); } diff --git a/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs index 8c535f842f0..efcee7f46c0 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs @@ -46,7 +46,10 @@ public DelegatePostProcessingConvention(string name, Action action /// Applies a post processing modification to the class map. /// /// The class map. - public void PostProcess(BsonClassMap classMap) + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + + /// + public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) { _action(classMap); } diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs index 55ad9a00b9e..49e18d31307 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs @@ -47,7 +47,10 @@ public EnumRepresentationConvention(BsonType representation) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { var memberType = memberMap.MemberType; var memberTypeInfo = memberType.GetTypeInfo(); diff --git a/src/MongoDB.Bson/Serialization/Conventions/IMemberMapConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/IMemberMapConvention.cs index b05f40d64ad..c32583b45b4 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/IMemberMapConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/IMemberMapConvention.cs @@ -25,5 +25,13 @@ public interface IMemberMapConvention : IConvention /// /// The member map. void Apply(BsonMemberMap memberMap); + + /// + /// //TODO + /// + /// + /// + void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain); + } } diff --git a/src/MongoDB.Bson/Serialization/Conventions/IPostProcessingConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/IPostProcessingConvention.cs index ddb7a095df5..d2d8df84944 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/IPostProcessingConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/IPostProcessingConvention.cs @@ -25,5 +25,12 @@ public interface IPostProcessingConvention : IConvention /// /// The class map. void PostProcess(BsonClassMap classMap); + + /// + /// //TODO + /// + /// + /// + void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain); } } diff --git a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs index aede146fe8c..79dcc621fb9 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs @@ -37,7 +37,10 @@ public IgnoreIfDefaultConvention(bool ignoreIfDefault) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { memberMap.SetIgnoreIfDefault(_ignoreIfDefault); } diff --git a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs index c99f694fe81..f2baec7dc91 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs @@ -37,7 +37,10 @@ public IgnoreIfNullConvention(bool ignoreIfNull) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { memberMap.SetIgnoreIfNull(_ignoreIfNull); } diff --git a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs index fa69c69c99b..86df5fd2027 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs @@ -23,12 +23,11 @@ namespace MongoDB.Bson.Serialization.Conventions /// public class LookupIdGeneratorConvention : ConventionBase, IPostProcessingConvention { - // public methods - /// - /// Applies a post processing modification to the class map. - /// - /// The class map. - public void PostProcess(BsonClassMap classMap) + /// + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + + /// + public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) { var idMemberMap = classMap.IdMemberMap; if (idMemberMap != null) @@ -36,7 +35,7 @@ public void PostProcess(BsonClassMap classMap) if (idMemberMap.IdGenerator == null) { //or we pass the domain to the BsonClassMap. The first probably makes more sense, but it's messier. - var idGenerator = BsonSerializer.LookupIdGenerator(idMemberMap.MemberType); //TODO ?? + var idGenerator = domain.LookupIdGenerator(idMemberMap.MemberType); if (idGenerator != null) { idMemberMap.SetIdGenerator(idGenerator); diff --git a/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs index 51ff212c300..07440a28597 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs @@ -43,7 +43,10 @@ public MemberDefaultValueConvention(Type type, object defaultValue) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { if (memberMap.MemberType == _type) { diff --git a/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs index bdee9118a15..193282ef797 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs @@ -28,7 +28,10 @@ public class MemberNameElementNameConvention : ConventionBase, IMemberMapConvent /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { memberMap.SetElementName(memberMap.MemberName); } diff --git a/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs index 82d295cb42f..49c62084468 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs @@ -30,7 +30,10 @@ public class NoIdMemberConvention : ConventionBase, IPostProcessingConvention /// Applies a post processing modification to the class map. /// /// The class map. - public void PostProcess(BsonClassMap classMap) + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + + /// + public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) { classMap.SetIdMember(null); } diff --git a/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs index add1d581121..af1d0eedf6b 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs @@ -150,7 +150,10 @@ public bool AllowDefaultFrameworkTypes /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { var serializer = memberMap.GetSerializer(); diff --git a/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs index ef21036c3e3..5971f97d32c 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs @@ -25,7 +25,10 @@ public class ResetMemberMapsConvention : ConventionBase, IMemberMapConvention /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { memberMap.Reset(); } diff --git a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs index ffa79944dd1..a6b3e108095 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs @@ -26,7 +26,10 @@ namespace MongoDB.Bson.Serialization.Conventions public class StringIdStoredAsObjectIdConvention : ConventionBase, IMemberMapConvention { /// - public void Apply(BsonMemberMap memberMap) + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + + /// + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { if (memberMap != memberMap.ClassMap.IdMemberMap) { @@ -38,7 +41,7 @@ public void Apply(BsonMemberMap memberMap) return; } - var defaultStringSerializer = BsonSerializer.LookupSerializer(typeof(string)); //TODO ?? + var defaultStringSerializer = domain.LookupSerializer(typeof(string)); //TODO ?? if (memberMap.GetSerializer() != defaultStringSerializer) { return; diff --git a/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs index 618d7213aec..9ea6db46264 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs @@ -29,7 +29,10 @@ public class StringObjectIdIdGeneratorConvention : ConventionBase, IPostProcessi /// Applies a post processing modification to the class map. /// /// The class map. - public void PostProcess(BsonClassMap classMap) + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + + /// + public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) { var idMemberMap = classMap.IdMemberMap; if (idMemberMap != null) From 7bec37fdbdf36b75e5dfe8411fa7763e34648a07 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:37:05 +0100 Subject: [PATCH 20/49] Correction --- .../Serialization/Serializers/ExpandoObjectSerializer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs index 489dba1f6ba..7160bc11288 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs @@ -29,13 +29,14 @@ namespace MongoDB.Bson.Serialization.Serializers public sealed class ExpandoObjectSerializer : DynamicDocumentBaseSerializer { // private fields - private IBsonSerializer> _listSerializer; + private readonly IBsonSerializer> _listSerializer; /// /// Initializes a new instance of the class. /// public ExpandoObjectSerializer() { + _listSerializer = BsonSerializer.LookupSerializer>(); } /// From bb395b0c098ef9cc0dcc73400185071fc6cf8eb1 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:38:16 +0100 Subject: [PATCH 21/49] Corrected convention tests --- tests/MongoDB.Bson.Tests/Jira/CSharp310Tests.cs | 5 +++++ .../Serialization/Conventions/ConventionRunnerTests.cs | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/tests/MongoDB.Bson.Tests/Jira/CSharp310Tests.cs b/tests/MongoDB.Bson.Tests/Jira/CSharp310Tests.cs index 976d9d3d5d4..79dcd48b02c 100644 --- a/tests/MongoDB.Bson.Tests/Jira/CSharp310Tests.cs +++ b/tests/MongoDB.Bson.Tests/Jira/CSharp310Tests.cs @@ -44,6 +44,11 @@ public void Apply(BsonMemberMap memberMap) memberMap.SetDefaultValue(Guid.Empty); } } + + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } } private static void InitializeSerialization() diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/ConventionRunnerTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/ConventionRunnerTests.cs index f86afe3836a..e477e80c952 100644 --- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/ConventionRunnerTests.cs +++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/ConventionRunnerTests.cs @@ -169,6 +169,11 @@ public void Apply(BsonMemberMap memberMap) RunCount++; RunOrder = _orderIndexProvider(); } + + public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } } private class TrackingAfterConvention : IPostProcessingConvention, ITrackRun @@ -194,6 +199,11 @@ public void PostProcess(BsonClassMap classMap) RunCount++; RunOrder = _orderIndexProvider(); } + + public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } } } } From d7756c67194ef21687ff32efeceb6f0aec5fc355 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:56:35 +0100 Subject: [PATCH 22/49] Removed multiple interfaces plus more fixes --- .../Serialization/BsonSerializationDomain.cs | 9 - .../HierarchicalDiscriminatorConvention.cs | 6 +- .../Conventions/IDiscriminatorConvention.cs | 19 ++ .../ObjectDiscriminatorConvention.cs | 12 + .../ScalarDiscriminatorConvention.cs | 6 +- .../StandardDiscriminatorConvention.cs | 13 +- .../Serialization/IBsonSerializationDomain.cs | 284 ++++++++---------- .../StandardDiscriminatorConventionTests.cs | 5 + .../Jira/CSharp5286Tests.cs | 9 + 9 files changed, 196 insertions(+), 167 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index cba4f3d2b84..e1322be8133 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -85,15 +85,6 @@ public ReaderWriterLockSlim ConfigLock get { return __configLock; } } - public IBsonCoreSerializerConfiguration SerializationConfiguration => this; - - // public methods - - public IBsonCoreSerializer BuildCoreSerializer() - { - return this; - } - /// /// Deserializes an object from a BsonDocument. /// diff --git a/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs index beebf06230e..aa249b62c62 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs @@ -41,7 +41,11 @@ public HierarchicalDiscriminatorConvention(string elementName) /// The nominal type. /// The actual type. /// The discriminator value. - public override BsonValue GetDiscriminator(Type nominalType, Type actualType) + public override BsonValue GetDiscriminator(Type nominalType, Type actualType) => + GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultDomain); + + /// + public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) { // TODO: this isn't quite right, not all classes are serialized using a class map serializer var classMap = BsonClassMap.LookupClassMap(actualType); diff --git a/src/MongoDB.Bson/Serialization/Conventions/IDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/IDiscriminatorConvention.cs index 242d0b557b2..11fa1528f01 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/IDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/IDiscriminatorConvention.cs @@ -36,6 +36,15 @@ public interface IDiscriminatorConvention /// The actual type. Type GetActualType(IBsonReader bsonReader, Type nominalType); + /// + /// //TODO + /// + /// + /// + /// + /// + Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain); + /// /// Gets the discriminator value for an actual type. /// @@ -43,5 +52,15 @@ public interface IDiscriminatorConvention /// The actual type. /// The discriminator value. BsonValue GetDiscriminator(Type nominalType, Type actualType); + + /// + /// //TODO + /// + /// + /// + /// + /// + BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain); + } } diff --git a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs index 34ad86da3c5..c269238dd20 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs @@ -144,6 +144,12 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) return nominalType; } + /// + public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } + /// /// Gets the discriminator value for an actual type. /// @@ -155,6 +161,12 @@ public BsonValue GetDiscriminator(Type nominalType, Type actualType) return TypeNameDiscriminator.GetDiscriminator(actualType); } + /// + public BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } + /// public override int GetHashCode() => 0; } diff --git a/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs index 7adf745fa25..dbb4d00871a 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs @@ -39,7 +39,11 @@ public ScalarDiscriminatorConvention(string elementName) /// The nominal type. /// The actual type. /// The discriminator value. - public override BsonValue GetDiscriminator(Type nominalType, Type actualType) + public override BsonValue GetDiscriminator(Type nominalType, Type actualType) => + GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultDomain); + + /// + public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) { // TODO: this isn't quite right, not all classes are serialized using a class map serializer var classMap = BsonClassMap.LookupClassMap(actualType); diff --git a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs index b1664389282..881447231e4 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs @@ -94,17 +94,21 @@ obj is StandardDiscriminatorConvention other && /// The reader. /// The nominal type. /// The actual type. - public Type GetActualType(IBsonReader bsonReader, Type nominalType) + public Type GetActualType(IBsonReader bsonReader, Type nominalType) => + GetActualType(bsonReader, nominalType, BsonSerializer.DefaultDomain); + + /// + public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain) { // the BsonReader is sitting at the value whose actual type needs to be found var bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.Document) { // ensure KnownTypes of nominalType are registered (so IsTypeDiscriminated returns correct answer) - BsonSerializer.EnsureKnownTypesAreRegistered(nominalType); //TODO ?? + domain.EnsureKnownTypesAreRegistered(nominalType); //TODO ?? // we can skip looking for a discriminator if nominalType has no discriminated sub types - if (BsonSerializer.IsTypeDiscriminated(nominalType)) //TODO ?? + if (domain.IsTypeDiscriminated(nominalType)) //TODO ?? { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); @@ -135,6 +139,9 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) /// The discriminator value. public abstract BsonValue GetDiscriminator(Type nominalType, Type actualType); + /// + public abstract BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain); + /// public override int GetHashCode() => 0; } diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index 9c1a3be8977..d927c5a39cb 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -9,33 +9,133 @@ namespace MongoDB.Bson.Serialization /// /// //TODO /// - public interface IBsonSerializationDomain : IBsonCoreSerializerConfigurator, IBsonCoreSerializerConfiguration, IBsonCoreSerializer + public interface IBsonSerializationDomain { - } + /// + /// Returns whether the given type has any discriminators registered for any of its subclasses. + /// + /// A Type. + /// True if the type is discriminated. + bool IsTypeDiscriminated(Type type); - internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain - { - ReaderWriterLockSlim ConfigLock { get; } + /// + /// Looks up the actual type of an object to be deserialized. + /// + /// The nominal type of the object. + /// The discriminator. + /// The actual type of the object. + Type LookupActualType(Type nominalType, BsonValue discriminator); - void EnsureKnownTypesAreRegistered(Type nominalType); + /// + /// Looks up the discriminator convention for a type. + /// + /// The type. + /// A discriminator convention. + IDiscriminatorConvention LookupDiscriminatorConvention(Type type); - IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, - IDiscriminatorConvention discriminatorConvention); + /// + /// Looks up an IdGenerator. + /// + /// The Id type. + /// An IdGenerator for the Id type. + IIdGenerator LookupIdGenerator(Type type); - bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type); - } + /// + /// Looks up a serializer for a Type. + /// + /// The type. + /// A serializer for type T. + IBsonSerializer LookupSerializer(); - /// - /// //TODO - /// - public interface IBsonCoreSerializer //TODO Don't like the name but have no better idea at the moment - { /// - /// //TODO + /// Looks up a serializer for a Type. + /// + /// The Type. + /// A serializer for the Type. + IBsonSerializer LookupSerializer(Type type); + + /// + /// Gets the serializer registry. + /// + IBsonSerializerRegistry SerializerRegistry { get; } + + /// + /// Registers the discriminator for a type. + /// + /// The type. + /// The discriminator. + void RegisterDiscriminator(Type type, BsonValue discriminator); + + /// + /// Registers the discriminator convention for a type. + /// + /// Type type. + /// The discriminator convention. + void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); + + /// + /// Registers a generic serializer definition for a generic type. + /// + /// The generic type. + /// The generic serializer definition. + void RegisterGenericSerializerDefinition( + Type genericTypeDefinition, + Type genericSerializerDefinition); + + /// + /// Registers an IdGenerator for an Id Type. + /// + /// The Id Type. + /// The IdGenerator for the Id Type. + void RegisterIdGenerator(Type type, IIdGenerator idGenerator); + + /// + /// Registers a serialization provider. + /// + /// The serialization provider. + void RegisterSerializationProvider(IBsonSerializationProvider provider); + + /// + /// Registers a serializer for a type. + /// + /// The type. + /// The serializer. + void RegisterSerializer(IBsonSerializer serializer); + + /// + /// Registers a serializer for a type. /// - IBsonCoreSerializerConfiguration SerializationConfiguration { get; } + /// The type. + /// The serializer. + void RegisterSerializer(Type type, IBsonSerializer serializer); /// + /// Tries to register a serializer for a type. + /// + /// The serializer. + /// The type. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(Type type, IBsonSerializer serializer); + + /// + /// Tries to register a serializer for a type. + /// + /// The type. + /// The serializer. + /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. + bool TryRegisterSerializer(IBsonSerializer serializer); + + /// + /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// + bool UseNullIdChecker { get; set; } + + /// + /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// + bool UseZeroIdChecker { get; set; } + + /// /// Deserializes an object from a BsonDocument. /// /// The nominal type of the object. @@ -183,157 +283,35 @@ void Serialize( object value, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)); - } - - /// - /// //TODO - /// - public interface IBsonCoreSerializerConfigurator - { - /// - /// Registers the discriminator for a type. - /// - /// The type. - /// The discriminator. - void RegisterDiscriminator(Type type, BsonValue discriminator); - - /// - /// Registers the discriminator convention for a type. - /// - /// Type type. - /// The discriminator convention. - void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention); - - /// - /// Registers a generic serializer definition for a generic type. - /// - /// The generic type. - /// The generic serializer definition. - void RegisterGenericSerializerDefinition( - Type genericTypeDefinition, - Type genericSerializerDefinition); - - /// - /// Registers an IdGenerator for an Id Type. - /// - /// The Id Type. - /// The IdGenerator for the Id Type. - void RegisterIdGenerator(Type type, IIdGenerator idGenerator); - - /// - /// Registers a serialization provider. - /// - /// The serialization provider. - void RegisterSerializationProvider(IBsonSerializationProvider provider); - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(IBsonSerializer serializer); - /// - /// Registers a serializer for a type. - /// - /// The type. - /// The serializer. - void RegisterSerializer(Type type, IBsonSerializer serializer); + //TODO These 3 methods were part of the internal interface before /// - /// Tries to register a serializer for a type. - /// - /// The serializer. - /// The type. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(Type type, IBsonSerializer serializer); - - /// - /// Tries to register a serializer for a type. - /// - /// The type. - /// The serializer. - /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. - bool TryRegisterSerializer(IBsonSerializer serializer); - - /// - /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. + /// //TODO /// - bool UseNullIdChecker { get; set; } //TODO It would be nice if this became a method (SetUseNullIdChecker) and the configuration would have only a getter + /// + void EnsureKnownTypesAreRegistered(Type nominalType); /// - /// Gets or sets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered. + /// //TODO /// - bool UseZeroIdChecker { get; set; } + /// + /// + /// + IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, + IDiscriminatorConvention discriminatorConvention); /// /// //TODO /// + /// /// - IBsonCoreSerializer BuildCoreSerializer(); + bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type); } - /// - /// //TODO - /// - public interface IBsonCoreSerializerConfiguration + internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain { - /// - /// Returns whether the given type has any discriminators registered for any of its subclasses. - /// - /// A Type. - /// True if the type is discriminated. - bool IsTypeDiscriminated(Type type); - - /// - /// Looks up the actual type of an object to be deserialized. - /// - /// The nominal type of the object. - /// The discriminator. - /// The actual type of the object. - Type LookupActualType(Type nominalType, BsonValue discriminator); - - /// - /// Looks up the discriminator convention for a type. - /// - /// The type. - /// A discriminator convention. - IDiscriminatorConvention LookupDiscriminatorConvention(Type type); - - /// - /// Looks up an IdGenerator. - /// - /// The Id type. - /// An IdGenerator for the Id type. - IIdGenerator LookupIdGenerator(Type type); - - /// - /// Looks up a serializer for a Type. - /// - /// The type. - /// A serializer for type T. - IBsonSerializer LookupSerializer(); - - /// - /// Looks up a serializer for a Type. - /// - /// The Type. - /// A serializer for the Type. - IBsonSerializer LookupSerializer(Type type); - - /// - /// Gets the serializer registry. - /// - IBsonSerializerRegistry SerializerRegistry { get; } - - /// - /// Gets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered is enabled. - /// - bool UseNullIdCheckerEnabled { get; } - - /// - /// Gets whether to use the ZeroIdChecker on value Id types that don't have an IdGenerator registered is enabled. - /// - bool UseZeroIdCheckerEnabled { get; } + ReaderWriterLockSlim ConfigLock { get; } } } \ No newline at end of file diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/StandardDiscriminatorConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/StandardDiscriminatorConventionTests.cs index f1d633bd724..b370126356b 100644 --- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/StandardDiscriminatorConventionTests.cs +++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/StandardDiscriminatorConventionTests.cs @@ -15,6 +15,7 @@ using System; using FluentAssertions; +using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Conventions; using Xunit; @@ -116,6 +117,10 @@ public ConcreteStandardDiscriminatorConvention(string elementName) } public override BsonValue GetDiscriminator(Type nominalType, Type actualType) => throw new NotImplementedException(); + public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } } public class DerivedFromConcreteStandardDiscriminatorConvention : ConcreteStandardDiscriminatorConvention diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5286Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5286Tests.cs index 4eaa8227360..06aa1c37530 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5286Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5286Tests.cs @@ -147,7 +147,16 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) }; } + public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } + public BsonValue GetDiscriminator(Type nominalType, Type actualType) => actualType.Name; + public BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) + { + throw new NotImplementedException(); + } public BsonValue[] GetDiscriminatorsForTypeAndSubTypes(Type type) { From 70f351bbf3a4c62668042a559169256196ec7f90 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 14:02:02 +0100 Subject: [PATCH 23/49] More improvements --- src/MongoDB.Bson/BsonExtensionMethods.cs | 75 ++++++++++++++++++- .../ObjectModel/BsonDocumentWrapper.cs | 60 +++++++++++++-- .../Serialization/BsonMemberMap.cs | 11 ++- .../BsonSerializationProviderBase.cs | 8 +- .../ObjectDiscriminatorConvention.cs | 14 ++-- .../StandardDiscriminatorConvention.cs | 2 +- .../Serialization/IBsonIdProvider.cs | 11 +++ .../Serializers/BsonDocumentSerializer.cs | 7 +- .../DiscriminatedInterfaceSerializer.cs | 23 +++++- .../Serializers/ExpandoObjectSerializer.cs | 11 ++- 10 files changed, 190 insertions(+), 32 deletions(-) diff --git a/src/MongoDB.Bson/BsonExtensionMethods.cs b/src/MongoDB.Bson/BsonExtensionMethods.cs index 6494a4c4b1c..99768d23510 100644 --- a/src/MongoDB.Bson/BsonExtensionMethods.cs +++ b/src/MongoDB.Bson/BsonExtensionMethods.cs @@ -69,6 +69,31 @@ public static byte[] ToBson( IBsonSerializer serializer = null, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs), + int estimatedBsonSize = 0) => ToBson(obj, nominalType, BsonSerializer.DefaultDomain, writerSettings, + serializer, configurator, args, estimatedBsonSize); + + /// + /// //TODO + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static byte[] ToBson( + this object obj, + Type nominalType, + IBsonSerializationDomain domain, + BsonBinaryWriterSettings writerSettings = null, + IBsonSerializer serializer = null, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs), int estimatedBsonSize = 0) { if (estimatedBsonSize < 0) @@ -84,7 +109,7 @@ public static byte[] ToBson( if (serializer == null) { - serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? + serializer = domain.LookupSerializer(nominalType); } if (serializer.ValueType != nominalType) { @@ -138,6 +163,27 @@ public static BsonDocument ToBsonDocument( Type nominalType, IBsonSerializer serializer = null, Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)) => ToBsonDocument(obj, nominalType, + BsonSerializer.DefaultDomain, serializer, configurator, args); + + /// + /// //TODO + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static BsonDocument ToBsonDocument( + this object obj, + Type nominalType, + IBsonSerializationDomain domain, + IBsonSerializer serializer = null, + Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)) { if (nominalType == null) @@ -165,7 +211,7 @@ public static BsonDocument ToBsonDocument( return convertibleToBsonDocument.ToBsonDocument(); // use the provided ToBsonDocument method } - serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? + serializer = domain.LookupSerializer(nominalType); //TODO ?? } if (serializer.ValueType != nominalType) { @@ -227,6 +273,29 @@ public static string ToJson( IBsonSerializer serializer = null, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)) + => ToJson(obj, nominalType, BsonSerializer.DefaultDomain, writerSettings, serializer, configurator, args); + + /// + /// //TODO + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static string ToJson( + this object obj, + Type nominalType, + IBsonSerializationDomain domain, + JsonWriterSettings writerSettings = null, + IBsonSerializer serializer = null, + Action configurator = null, + BsonSerializationArgs args = default(BsonSerializationArgs)) { if (nominalType == null) { @@ -236,7 +305,7 @@ public static string ToJson( if (serializer == null) { - serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? + serializer = domain.LookupSerializer(nominalType); } if (serializer.ValueType != nominalType) { diff --git a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs index 1a19e75c857..ed6d0f0e565 100644 --- a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs +++ b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs @@ -91,9 +91,19 @@ public object Wrapped /// The nominal type of the wrapped object. /// The wrapped object. /// A BsonDocumentWrapper. - public static BsonDocumentWrapper Create(TNominalType value) + public static BsonDocumentWrapper Create(TNominalType value) => + Create(value, BsonSerializer.DefaultDomain); + + /// + /// //TODO + /// + /// + /// + /// + /// + public static BsonDocumentWrapper Create(TNominalType value, IBsonSerializationDomain domain) { - return Create(typeof(TNominalType), value); + return Create(typeof(TNominalType), value, domain); } /// @@ -102,9 +112,19 @@ public static BsonDocumentWrapper Create(TNominalType value) /// The nominal type of the wrapped object. /// The wrapped object. /// A BsonDocumentWrapper. - public static BsonDocumentWrapper Create(Type nominalType, object value) + public static BsonDocumentWrapper Create(Type nominalType, object value) => + Create(nominalType, value, BsonSerializer.DefaultDomain); + + /// + /// //TODO + /// + /// + /// + /// + /// + public static BsonDocumentWrapper Create(Type nominalType, object value, IBsonSerializationDomain domain) { - var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? + var serializer = domain.LookupSerializer(nominalType); //TODO ?? return new BsonDocumentWrapper(value, serializer); } @@ -114,14 +134,25 @@ public static BsonDocumentWrapper Create(Type nominalType, object value) /// The nominal type of the wrapped objects. /// A list of wrapped objects. /// A list of BsonDocumentWrappers. - public static IEnumerable CreateMultiple(IEnumerable values) + public static IEnumerable CreateMultiple(IEnumerable values) => + CreateMultiple(values, BsonSerializer.DefaultDomain); + + /// + /// //TODO + /// + /// + /// + /// + /// + /// + public static IEnumerable CreateMultiple(IEnumerable values, IBsonSerializationDomain domain) { if (values == null) { throw new ArgumentNullException("values"); } - var serializer = BsonSerializer.LookupSerializer(typeof(TNominalType)); //TODO ?? + var serializer = domain.LookupSerializer(typeof(TNominalType)); return values.Select(v => new BsonDocumentWrapper(v, serializer)); } @@ -131,7 +162,18 @@ public static IEnumerable CreateMultiple(IEnu /// The nominal type of the wrapped object. /// A list of wrapped objects. /// A list of BsonDocumentWrappers. - public static IEnumerable CreateMultiple(Type nominalType, IEnumerable values) + public static IEnumerable CreateMultiple(Type nominalType, IEnumerable values) => + CreateMultiple(nominalType, values, BsonSerializer.DefaultDomain); + + /// + /// //TODO + /// + /// + /// + /// + /// + /// + public static IEnumerable CreateMultiple(Type nominalType, IEnumerable values, IBsonSerializationDomain domain) { if (nominalType == null) { @@ -142,10 +184,12 @@ public static IEnumerable CreateMultiple(Type nominalType, throw new ArgumentNullException("values"); } - var serializer = BsonSerializer.LookupSerializer(nominalType); //TODO ?? + var serializer = domain.LookupSerializer(nominalType); return values.Cast().Select(v => new BsonDocumentWrapper(v, serializer)); } + + // public methods /// /// Creates a shallow clone of the document (see also DeepClone). diff --git a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs index 98bdbbe4aab..ad5bf481f4d 100644 --- a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs @@ -294,14 +294,21 @@ obj is BsonMemberMap other && /// Gets the serializer. /// /// The serializer. - public IBsonSerializer GetSerializer() + public IBsonSerializer GetSerializer() => GetSerializer(BsonSerializer.DefaultDomain); + + /// + /// //TODO + /// + /// + /// + public IBsonSerializer GetSerializer(IBsonSerializationDomain domain) { if (_serializer == null) { // return special serializer for BsonValue members that handles the _csharpnull representation if (_memberTypeIsBsonValue) { - var wrappedSerializer = BsonSerializer.LookupSerializer(_memberType); //TODO ?? + var wrappedSerializer = domain.LookupSerializer(_memberType); var isBsonArraySerializer = wrappedSerializer is IBsonArraySerializer; var isBsonDocumentSerializer = wrappedSerializer is IBsonDocumentSerializer; diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs b/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs index 93195b5b773..bb19d0bd0e3 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationProviderBase.cs @@ -24,9 +24,9 @@ namespace MongoDB.Bson.Serialization public abstract class BsonSerializationProviderBase : IRegistryAwareBsonSerializationProvider { /// - public virtual IBsonSerializer GetSerializer(Type type) //TODO We can keep this as is + public virtual IBsonSerializer GetSerializer(Type type) { - return GetSerializer(type, BsonSerializer.SerializerRegistry); + return GetSerializer(type, BsonSerializer.SerializerRegistry); //TODO We can keep this as is } /// @@ -38,9 +38,9 @@ public virtual IBsonSerializer GetSerializer(Type type) //TODO We can keep this /// The serializer type definition. /// The type arguments. /// A serializer. - protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDefinition, params Type[] typeArguments) //TODO We can keep this as is + protected virtual IBsonSerializer CreateGenericSerializer(Type serializerTypeDefinition, params Type[] typeArguments) { - return CreateGenericSerializer(serializerTypeDefinition, typeArguments, BsonSerializer.SerializerRegistry); + return CreateGenericSerializer(serializerTypeDefinition, typeArguments, BsonSerializer.SerializerRegistry); //TODO We can keep this as is } /// diff --git a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs index c269238dd20..ca8e04da3ae 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs @@ -86,7 +86,11 @@ obj is ObjectDiscriminatorConvention other && /// The reader. /// The nominal type. /// The actual type. - public Type GetActualType(IBsonReader bsonReader, Type nominalType) + public Type GetActualType(IBsonReader bsonReader, Type nominalType) => + GetActualType(bsonReader, nominalType, BsonSerializer.DefaultDomain); + + /// + public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain) { // the BsonReader is sitting at the value whose actual type needs to be found var bsonType = bsonReader.GetCurrentBsonType(); @@ -135,7 +139,7 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } - actualType = BsonSerializer.LookupActualType(nominalType, discriminator); //TODO ?? + actualType = domain.LookupActualType(nominalType, discriminator); } bsonReader.ReturnToBookmark(bookmark); return actualType; @@ -144,12 +148,6 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType) return nominalType; } - /// - public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain) - { - throw new NotImplementedException(); - } - /// /// Gets the discriminator value for an actual type. /// diff --git a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs index 881447231e4..16815ada484 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs @@ -121,7 +121,7 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSeriali { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } - actualType = BsonSerializer.LookupActualType(nominalType, discriminator); //TODO ?? + actualType = domain.LookupActualType(nominalType, discriminator); } bsonReader.ReturnToBookmark(bookmark); return actualType; diff --git a/src/MongoDB.Bson/Serialization/IBsonIdProvider.cs b/src/MongoDB.Bson/Serialization/IBsonIdProvider.cs index 6cb9ba4a811..c7ca28414b4 100644 --- a/src/MongoDB.Bson/Serialization/IBsonIdProvider.cs +++ b/src/MongoDB.Bson/Serialization/IBsonIdProvider.cs @@ -32,6 +32,17 @@ public interface IBsonIdProvider /// True if the document has an Id. bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator); + /// + /// //TODO + /// + /// + /// + /// + /// + /// + /// + bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType, out IIdGenerator idGenerator); + /// /// Sets the document Id. /// diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs index 0091c927ffe..465f312db0a 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs @@ -81,6 +81,11 @@ public bool GetDocumentId( object document, out object id, out Type idNominalType, + out IIdGenerator idGenerator) => GetDocumentId(document, BsonSerializer.DefaultDomain, out id, + out idNominalType, out idGenerator); + + /// + public bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType, out IIdGenerator idGenerator) { var bsonDocument = (BsonDocument)document; @@ -89,7 +94,7 @@ public bool GetDocumentId( if (bsonDocument.TryGetValue("_id", out idBsonValue)) { id = idBsonValue; - idGenerator = BsonSerializer.LookupIdGenerator(id.GetType()); //TODO ?? + idGenerator = domain.LookupIdGenerator(id.GetType()); if (idGenerator == null) { diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs index a5334d85e76..75afa999605 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs @@ -41,13 +41,13 @@ public sealed class DiscriminatedInterfaceSerializer : // where TInterface is an interface { #region static - private static IBsonSerializer CreateInterfaceSerializer() + private static IBsonSerializer CreateInterfaceSerializer(IBsonSerializationDomain domain) { var classMapDefinition = typeof(BsonClassMap<>); var classMapType = classMapDefinition.MakeGenericType(typeof(TInterface)); var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); classMap.AutoMap(); - classMap.SetDiscriminatorConvention(BsonSerializer.LookupDiscriminatorConvention(typeof(TInterface))); //TODO ?? + classMap.SetDiscriminatorConvention(domain.LookupDiscriminatorConvention(typeof(TInterface))); classMap.Freeze(); return new BsonClassMapSerializer(classMap); } @@ -75,7 +75,7 @@ public DiscriminatedInterfaceSerializer() /// interfaceType /// interfaceType public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorConvention) - : this(discriminatorConvention, CreateInterfaceSerializer()) + : this(discriminatorConvention, interfaceSerializer: null) { } @@ -87,7 +87,22 @@ public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorCo /// interfaceType /// interfaceType public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorConvention, IBsonSerializer interfaceSerializer) + : this(discriminatorConvention, interfaceSerializer, BsonSerializer.DefaultDomain) { + } + + /// + /// //TODO + /// + /// + /// + /// + /// + /// + public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorConvention, IBsonSerializer interfaceSerializer, IBsonSerializationDomain domain) + { + interfaceSerializer ??= CreateInterfaceSerializer(domain); + var interfaceTypeInfo = typeof(TInterface).GetTypeInfo(); if (!interfaceTypeInfo.IsInterface) { @@ -97,7 +112,7 @@ public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorCo _interfaceType = typeof(TInterface); _discriminatorConvention = discriminatorConvention ?? interfaceSerializer.GetDiscriminatorConvention(); - _objectSerializer = BsonSerializer.LookupSerializer(); //TODO ?? + _objectSerializer = domain.LookupSerializer(); if (_objectSerializer is ObjectSerializer standardObjectSerializer) { _objectSerializer = standardObjectSerializer.WithDiscriminatorConvention(_discriminatorConvention); diff --git a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs index 7160bc11288..8081bee4bbe 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs @@ -35,8 +35,17 @@ public sealed class ExpandoObjectSerializer : DynamicDocumentBaseSerializer class. /// public ExpandoObjectSerializer() + :this(BsonSerializer.DefaultDomain.SerializerRegistry) { - _listSerializer = BsonSerializer.LookupSerializer>(); + } + + /// + /// //TODO + /// + /// + public ExpandoObjectSerializer(IBsonSerializerRegistry serializerRegistry) + { + _listSerializer = serializerRegistry.GetSerializer>(); } /// From cc40c72aefdf2548a2ebbf57d3481dbc635d93ea Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 14:04:36 +0100 Subject: [PATCH 24/49] Small fixes --- .../Serialization/Serializers/BsonClassMapSerializer.cs | 5 +++++ src/MongoDB.Driver/OfTypeSerializer.cs | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs index 947a4c58369..8dbc8e3c019 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs @@ -326,6 +326,11 @@ public bool GetDocumentId( out object id, out Type idNominalType, out IIdGenerator idGenerator) + => GetDocumentId(document, BsonSerializer.DefaultDomain, out id, out idNominalType, out idGenerator); + + /// + public bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType, + out IIdGenerator idGenerator) { var idMemberMap = _classMap.IdMemberMap; if (idMemberMap != null) diff --git a/src/MongoDB.Driver/OfTypeSerializer.cs b/src/MongoDB.Driver/OfTypeSerializer.cs index 1ff1b95e4c2..a95c2f1a22f 100644 --- a/src/MongoDB.Driver/OfTypeSerializer.cs +++ b/src/MongoDB.Driver/OfTypeSerializer.cs @@ -45,7 +45,12 @@ obj is OfTypeSerializer other && object.Equals(_derivedDocumentSerializer, other._derivedDocumentSerializer); } - public bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) + public bool + GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) + => GetDocumentId(document, BsonSerializer.DefaultDomain, out id, out idNominalType, out idGenerator); + + public bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType, + out IIdGenerator idGenerator) { if (_derivedDocumentSerializer is IBsonIdProvider idProvider) { From 04d45faf5fecc5d5017b630c2b2364b47a1b9fcd Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 27 Jan 2025 14:57:34 +0100 Subject: [PATCH 25/49] Small fixes --- src/MongoDB.Bson/BsonExtensionMethods.cs | 2 +- src/MongoDB.Driver/MongoCollectionSettings.cs | 22 +++++++++++++++++-- .../uuid/prose-tests/ImplicitEncodingTests.cs | 8 +++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/MongoDB.Bson/BsonExtensionMethods.cs b/src/MongoDB.Bson/BsonExtensionMethods.cs index 99768d23510..ec714b022a9 100644 --- a/src/MongoDB.Bson/BsonExtensionMethods.cs +++ b/src/MongoDB.Bson/BsonExtensionMethods.cs @@ -121,7 +121,7 @@ public static byte[] ToBson( { using (var bsonWriter = new BsonBinaryWriter(memoryStream, writerSettings ?? BsonBinaryWriterSettings.Defaults)) { - var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator); + var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator).With(c => c.Domain = domain); serializer.Serialize(context, args, obj); } return memoryStream.ToArray(); diff --git a/src/MongoDB.Driver/MongoCollectionSettings.cs b/src/MongoDB.Driver/MongoCollectionSettings.cs index a8489008921..31625f1c336 100644 --- a/src/MongoDB.Driver/MongoCollectionSettings.cs +++ b/src/MongoDB.Driver/MongoCollectionSettings.cs @@ -34,6 +34,7 @@ public class MongoCollectionSettings private Setting _readPreference; private Setting _writeConcern; private Setting _writeEncoding; + private Setting _serializationDomain; // the following fields are set when Freeze is called private bool _isFrozen; @@ -116,9 +117,26 @@ public ReadPreference ReadPreference /// /// Gets the serializer registry. /// - public IBsonSerializerRegistry SerializerRegistry + public IBsonSerializerRegistry SerializerRegistry => + _serializationDomain.HasBeenSet + ? SerializationDomain.SerializerRegistry + : BsonSerializer.SerializerRegistry; + + /// + /// //TODO + /// + public IBsonSerializationDomain SerializationDomain { - get { return BsonSerializer.SerializerRegistry; } + get => _serializationDomain.Value; + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } + if (value == null) + { + throw new ArgumentNullException("value"); + } + _serializationDomain.Value = value; + } } /// diff --git a/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs b/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs index 43595ab688c..fe30b066b46 100644 --- a/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs +++ b/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs @@ -82,6 +82,14 @@ public void Implicit_encoding_with_pyton_legacy_representation_should_work_as_ex binaryData.Bytes.Should().Equal(BsonUtils.ParseHexString("00112233445566778899aabbccddeeff")); } + public class Person + { + [BsonId] + public ObjectId Id { get; set; } + public string Name { get; set; } + public int Age { get; set; } + } + [Fact] public void Implicit_encoding_with_standard_representation_should_work_as_expected() { From 8305dc19b3f23c5b57e2dd2ba96c5f6415f8ad43 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 28 Jan 2025 11:22:55 +0100 Subject: [PATCH 26/49] improvements --- .../BsonDeserializationContext.cs | 3 +- .../Serialization/BsonSerializationContext.cs | 3 +- .../Serialization/BsonSerializer.cs | 7 ++ src/MongoDB.Driver/MongoClientSettings.cs | 20 ++++ .../MultipleRegistriesTests.cs | 105 ++++++++++++++++++ .../uuid/prose-tests/ImplicitEncodingTests.cs | 8 -- 6 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index 577c309f86d..1faed2df717 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -44,8 +44,7 @@ private BsonDeserializationContext( _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; - _domain = domain; - // _domain = domain ?? BsonSerializer.DefaultDomain; //TODO We could do this here, but let's keep it as the previous line to catch errors. + _domain = domain ?? BsonSerializer.DefaultDomain; } // public properties diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs index c327c15b7c3..8bce28575c5 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs @@ -36,8 +36,7 @@ private BsonSerializationContext( { _writer = writer; _isDynamicType = isDynamicType; - _domain = domain; - // _domain = domain ?? BsonSerializer.DefaultDomain; //TODO We could do this here, but let's keep it as the previous line to catch errors. + _domain = domain ?? BsonSerializer.DefaultDomain; } // public properties diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index a2a21042929..4590928edde 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -67,6 +67,13 @@ public static bool UseZeroIdChecker internal static ReaderWriterLockSlim ConfigLock => _domain.ConfigLock; // public static methods + + /// + /// //TODO + /// + /// + public static IBsonSerializationDomain CreateDomain() => new BsonSerializationDomain(); + /// /// Deserializes an object from a BsonDocument. /// diff --git a/src/MongoDB.Driver/MongoClientSettings.cs b/src/MongoDB.Driver/MongoClientSettings.cs index d7da362ca92..d0e70b37c1e 100644 --- a/src/MongoDB.Driver/MongoClientSettings.cs +++ b/src/MongoDB.Driver/MongoClientSettings.cs @@ -18,6 +18,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Text; +using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Compression; using MongoDB.Driver.Core.Configuration; using MongoDB.Driver.Core.Misc; @@ -47,6 +48,7 @@ public class MongoClientSettings : IEquatable, IInheritable private TimeSpan _connectTimeout; private MongoCredential _credential; private bool _directConnection; + private IBsonSerializationDomain _domain; private TimeSpan _heartbeatInterval; private TimeSpan _heartbeatTimeout; private bool _ipv6; @@ -99,6 +101,7 @@ public MongoClientSettings() _compressors = new CompressorConfiguration[0]; _connectTimeout = MongoDefaults.ConnectTimeout; _directConnection = false; + _domain = null; _heartbeatInterval = ServerSettings.DefaultHeartbeatInterval; _heartbeatTimeout = ServerSettings.DefaultHeartbeatTimeout; _ipv6 = false; @@ -264,6 +267,23 @@ public bool DirectConnection } } + /// + /// //TODO + /// + /// + public IBsonSerializationDomain Domain + { + get + { + return _domain; + } + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoClientSettings is frozen."); } + _domain = value; + } + } + /// /// Gets a value indicating whether the settings have been frozen to prevent further changes. /// diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs new file mode 100644 index 00000000000..fd9ed2bc3a8 --- /dev/null +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -0,0 +1,105 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Linq; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Bson.Serialization.Serializers; +using Xunit; + +namespace MongoDB.Driver.Tests +{ + public class MultipleRegistriesTests + { + [Fact] + public void GeneralTest() + { + // { + // var client = DriverTestConfiguration.CreateMongoClient(c => c.Domain = BsonSerializer.DefaultDomain); + // var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); + // db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + // var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + // var bsonCollection = + // db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + // + // var person = new Person { Id = ObjectId.Parse("6797b56bf5495bf53aa3078f"), Name = "Mario", Age = 24 }; + // collection.InsertOne(person); + // + // var retrieved = bsonCollection.FindSync("{}").ToList().Single(); + // var toString = retrieved.ToString(); + // + // var expectedVal = + // """{ "_id" : { "$oid" : "6797b56bf5495bf53aa3078f" }, "Name" : "Mario", "Age" : 24 }"""; + // Assert.Equal(expectedVal, toString); + // } + + { + var customDomain = BsonSerializer.CreateDomain(); + customDomain.RegisterSerializer(new CustomStringSerializer()); + + var client = DriverTestConfiguration.CreateMongoClient(c => c.Domain = customDomain); + var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); + db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + var bsonCollection = + db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + + var person = new Person { Id = ObjectId.Parse("6797b56bf5495bf53aa3078f"), Name = "Mario", Age = 24 }; + collection.InsertOne(person); + + var retrieved = bsonCollection.FindSync("{}").ToList().Single(); + var toString = retrieved.ToString(); + + var expectedVal = + """{ "_id" : { "$oid" : "6797b56bf5495bf53aa3078f" }, "Name" : "Mariotest", "Age" : 24 }"""; + Assert.Equal(expectedVal, toString); + } + } + + public class Person + { + [BsonId] public ObjectId Id { get; set; } + public string Name { get; set; } + public int Age { get; set; } + } + + public class CustomStringSerializer : SealedClassSerializerBase + { + /// + public override int GetHashCode() => 0; + + protected override string DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var bsonReader = context.Reader; + + var bsonType = bsonReader.GetCurrentBsonType(); + return bsonType switch + { + BsonType.String => bsonReader.ReadString(), + BsonType.Symbol => bsonReader.ReadSymbol(), + _ => throw CreateCannotDeserializeFromBsonTypeException(bsonType) + }; + } + + protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, + string value) + { + var bsonWriter = context.Writer; + bsonWriter.WriteString(value + "test"); + } + } + } +} \ No newline at end of file diff --git a/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs b/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs index fe30b066b46..43595ab688c 100644 --- a/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs +++ b/tests/MongoDB.Driver.Tests/Specifications/uuid/prose-tests/ImplicitEncodingTests.cs @@ -82,14 +82,6 @@ public void Implicit_encoding_with_pyton_legacy_representation_should_work_as_ex binaryData.Bytes.Should().Equal(BsonUtils.ParseHexString("00112233445566778899aabbccddeeff")); } - public class Person - { - [BsonId] - public ObjectId Id { get; set; } - public string Name { get; set; } - public int Age { get; set; } - } - [Fact] public void Implicit_encoding_with_standard_representation_should_work_as_expected() { From 402a8898f5c363717d2e1826da0b553f9fb89bc4 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:23:23 +0100 Subject: [PATCH 27/49] Small fix --- .../Serialization/Serializers/BsonClassMapSerializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs index 8dbc8e3c019..6eff0f30971 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs @@ -689,7 +689,7 @@ private void SerializeNormalMember(BsonSerializationContext context, object obj, } bsonWriter.WriteName(memberMap.ElementName); - memberMap.GetSerializer().Serialize(context, value); + memberMap.GetSerializer(context.Domain).Serialize(context, value); } private bool ShouldSerializeDiscriminator(Type nominalType) From 6d2faf99e68269e5d5631b3f350def820d3c0cf6 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Thu, 30 Jan 2025 17:24:25 +0100 Subject: [PATCH 28/49] Various fixes --- .../Encoders/MessageEncoderSettings.cs | 1 + .../IInheritableMongoClientSettings.cs | 2 ++ src/MongoDB.Driver/MongoClientSettings.cs | 36 +++++++++---------- src/MongoDB.Driver/MongoCollectionImpl.cs | 3 +- src/MongoDB.Driver/MongoCollectionSettings.cs | 9 ++--- src/MongoDB.Driver/MongoDatabaseSettings.cs | 23 ++++++++++-- .../MultipleRegistriesTests.cs | 4 +-- 7 files changed, 50 insertions(+), 28 deletions(-) diff --git a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/MessageEncoderSettings.cs b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/MessageEncoderSettings.cs index 30c2e33e2fd..55f3caff990 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/MessageEncoderSettings.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/MessageEncoderSettings.cs @@ -41,6 +41,7 @@ internal static class MessageEncoderSettingsName public const string ShellVersion = nameof(ShellVersion); // other encoders (if any) might use additional settings + public const string SerializationDomain = nameof(SerializationDomain); } internal sealed class MessageEncoderSettings : IEnumerable> diff --git a/src/MongoDB.Driver/IInheritableMongoClientSettings.cs b/src/MongoDB.Driver/IInheritableMongoClientSettings.cs index 04eb99990f3..797141137d4 100644 --- a/src/MongoDB.Driver/IInheritableMongoClientSettings.cs +++ b/src/MongoDB.Driver/IInheritableMongoClientSettings.cs @@ -16,6 +16,7 @@ using System; using System.Text; using MongoDB.Bson; +using MongoDB.Bson.Serialization; namespace MongoDB.Driver { @@ -24,6 +25,7 @@ internal interface IInheritableMongoClientSettings ReadConcern ReadConcern { get; } UTF8Encoding ReadEncoding { get; } ReadPreference ReadPreference { get; } + IBsonSerializationDomain SerializationDomain { get; } WriteConcern WriteConcern { get; } UTF8Encoding WriteEncoding { get; } } diff --git a/src/MongoDB.Driver/MongoClientSettings.cs b/src/MongoDB.Driver/MongoClientSettings.cs index d0e70b37c1e..d3123c0b2c5 100644 --- a/src/MongoDB.Driver/MongoClientSettings.cs +++ b/src/MongoDB.Driver/MongoClientSettings.cs @@ -48,7 +48,6 @@ public class MongoClientSettings : IEquatable, IInheritable private TimeSpan _connectTimeout; private MongoCredential _credential; private bool _directConnection; - private IBsonSerializationDomain _domain; private TimeSpan _heartbeatInterval; private TimeSpan _heartbeatTimeout; private bool _ipv6; @@ -68,6 +67,7 @@ public class MongoClientSettings : IEquatable, IInheritable private bool _retryReads; private bool _retryWrites; private ConnectionStringScheme _scheme; + private IBsonSerializationDomain _serializationDomain; private ServerApi _serverApi; private List _servers; private ServerMonitoringMode _serverMonitoringMode; @@ -101,7 +101,6 @@ public MongoClientSettings() _compressors = new CompressorConfiguration[0]; _connectTimeout = MongoDefaults.ConnectTimeout; _directConnection = false; - _domain = null; _heartbeatInterval = ServerSettings.DefaultHeartbeatInterval; _heartbeatTimeout = ServerSettings.DefaultHeartbeatTimeout; _ipv6 = false; @@ -120,6 +119,7 @@ public MongoClientSettings() _retryReads = true; _retryWrites = true; _scheme = ConnectionStringScheme.MongoDB; + _serializationDomain = BsonSerializer.DefaultDomain; _serverApi = null; _servers = new List { new MongoServerAddress("localhost") }; _serverMonitoringMode = ServerMonitoringMode.Auto; @@ -267,23 +267,6 @@ public bool DirectConnection } } - /// - /// //TODO - /// - /// - public IBsonSerializationDomain Domain - { - get - { - return _domain; - } - set - { - if (_isFrozen) { throw new InvalidOperationException("MongoClientSettings is frozen."); } - _domain = value; - } - } - /// /// Gets a value indicating whether the settings have been frozen to prevent further changes. /// @@ -491,6 +474,21 @@ public ReadPreference ReadPreference } } + /// + /// //TODO + /// + /// + /// + public IBsonSerializationDomain SerializationDomain + { + get => _serializationDomain; + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoClientSettings is frozen."); } + _serializationDomain = value ?? throw new ArgumentNullException(nameof(value)); + } + } + /// /// Gets or sets the name of the replica set. /// diff --git a/src/MongoDB.Driver/MongoCollectionImpl.cs b/src/MongoDB.Driver/MongoCollectionImpl.cs index 51f03dc0a04..ae27cfe5fa7 100644 --- a/src/MongoDB.Driver/MongoCollectionImpl.cs +++ b/src/MongoDB.Driver/MongoCollectionImpl.cs @@ -1320,7 +1320,8 @@ private MessageEncoderSettings GetMessageEncoderSettings() var messageEncoderSettings = new MessageEncoderSettings { { MessageEncoderSettingsName.ReadEncoding, _settings.ReadEncoding ?? Utf8Encodings.Strict }, - { MessageEncoderSettingsName.WriteEncoding, _settings.WriteEncoding ?? Utf8Encodings.Strict } + { MessageEncoderSettingsName.WriteEncoding, _settings.WriteEncoding ?? Utf8Encodings.Strict }, + { MessageEncoderSettingsName.SerializationDomain, _settings.SerializationDomain } }; if (_database.Client is MongoClient mongoClient) diff --git a/src/MongoDB.Driver/MongoCollectionSettings.cs b/src/MongoDB.Driver/MongoCollectionSettings.cs index 31625f1c336..44ecb254646 100644 --- a/src/MongoDB.Driver/MongoCollectionSettings.cs +++ b/src/MongoDB.Driver/MongoCollectionSettings.cs @@ -117,10 +117,7 @@ public ReadPreference ReadPreference /// /// Gets the serializer registry. /// - public IBsonSerializerRegistry SerializerRegistry => - _serializationDomain.HasBeenSet - ? SerializationDomain.SerializerRegistry - : BsonSerializer.SerializerRegistry; + public IBsonSerializerRegistry SerializerRegistry => SerializationDomain.SerializerRegistry; /// /// //TODO @@ -316,6 +313,10 @@ internal void ApplyDefaultValues(MongoDatabaseSettings databaseSettings) { ReadPreference = databaseSettings.ReadPreference; } + if (!_serializationDomain.HasBeenSet) + { + SerializationDomain = databaseSettings.SerializationDomain; + } if (!_writeConcern.HasBeenSet) { WriteConcern = databaseSettings.WriteConcern; diff --git a/src/MongoDB.Driver/MongoDatabaseSettings.cs b/src/MongoDB.Driver/MongoDatabaseSettings.cs index b82ea52828d..9ba9fe0f0db 100644 --- a/src/MongoDB.Driver/MongoDatabaseSettings.cs +++ b/src/MongoDB.Driver/MongoDatabaseSettings.cs @@ -33,6 +33,7 @@ public class MongoDatabaseSettings private Setting _readPreference; private Setting _writeConcern; private Setting _writeEncoding; + private Setting _serializationDomain; // the following fields are set when Freeze is called private bool _isFrozen; @@ -101,9 +102,23 @@ public ReadPreference ReadPreference /// /// Gets the serializer registry. /// - public IBsonSerializerRegistry SerializerRegistry + public IBsonSerializerRegistry SerializerRegistry => SerializationDomain.SerializerRegistry; + + /// + /// //TODO + /// + public IBsonSerializationDomain SerializationDomain { - get { return BsonSerializer.SerializerRegistry; } + get => _serializationDomain.Value; + set + { + if (_isFrozen) { throw new InvalidOperationException("MongoCollectionSettings is frozen."); } + if (value == null) + { + throw new ArgumentNullException("value"); + } + _serializationDomain.Value = value; + } } /// @@ -275,6 +290,10 @@ internal void ApplyDefaultValues(IInheritableMongoClientSettings clientSettings) { ReadPreference = clientSettings.ReadPreference; } + if (!_serializationDomain.HasBeenSet) + { + SerializationDomain = clientSettings.SerializationDomain; + } if (!_writeConcern.HasBeenSet) { WriteConcern = clientSettings.WriteConcern; diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs index fd9ed2bc3a8..a1286faf941 100644 --- a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -28,7 +28,7 @@ public class MultipleRegistriesTests public void GeneralTest() { // { - // var client = DriverTestConfiguration.CreateMongoClient(c => c.Domain = BsonSerializer.DefaultDomain); + // var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = BsonSerializer.DefaultDomain); // var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); // db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); // var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); @@ -50,7 +50,7 @@ public void GeneralTest() var customDomain = BsonSerializer.CreateDomain(); customDomain.RegisterSerializer(new CustomStringSerializer()); - var client = DriverTestConfiguration.CreateMongoClient(c => c.Domain = customDomain); + var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = customDomain); var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); From 5ac0c06846a95b7c054fe0147b3fea97245a70cc Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Thu, 30 Jan 2025 18:23:46 +0100 Subject: [PATCH 29/49] First test passing --- src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs | 4 +++- src/MongoDB.Bson/IO/BsonWriterSettings.cs | 15 +++++++++++++++ .../Serialization/BsonDeserializationContext.cs | 3 ++- src/MongoDB.Bson/Serialization/BsonMemberMap.cs | 2 +- .../Serialization/BsonSerializationContext.cs | 4 ++-- .../Serialization/BsonSerializationDomain.cs | 5 ++++- src/MongoDB.Bson/Serialization/BsonSerializer.cs | 2 +- .../BinaryEncoders/MessageBinaryEncoderBase.cs | 7 +++++++ .../JsonEncoders/MessageJsonEncoderBase.cs | 5 +++++ src/MongoDB.Driver/MongoClientSettings.cs | 1 + .../MultipleRegistriesTests.cs | 1 + 11 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs b/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs index 96c8f3168de..a59c9372176 100644 --- a/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs +++ b/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs @@ -15,6 +15,7 @@ using System; using System.Text; +using MongoDB.Bson.Serialization; namespace MongoDB.Bson.IO { @@ -122,7 +123,8 @@ protected override BsonWriterSettings CloneImplementation() Encoding = _encoding, FixOldBinarySubTypeOnOutput = _fixOldBinarySubTypeOnOutput, MaxDocumentSize = _maxDocumentSize, - MaxSerializationDepth = MaxSerializationDepth + MaxSerializationDepth = MaxSerializationDepth, + SerializationDomain = SerializationDomain, }; return clone; } diff --git a/src/MongoDB.Bson/IO/BsonWriterSettings.cs b/src/MongoDB.Bson/IO/BsonWriterSettings.cs index 06957993d70..c4730dce269 100644 --- a/src/MongoDB.Bson/IO/BsonWriterSettings.cs +++ b/src/MongoDB.Bson/IO/BsonWriterSettings.cs @@ -14,6 +14,7 @@ */ using System; +using MongoDB.Bson.Serialization; namespace MongoDB.Bson.IO { @@ -25,6 +26,7 @@ public abstract class BsonWriterSettings // private fields private bool _isFrozen; private int _maxSerializationDepth = BsonDefaults.MaxSerializationDepth; + private IBsonSerializationDomain _serializationDomain; // constructors /// @@ -92,6 +94,19 @@ public BsonWriterSettings FrozenCopy() } } + /// + /// //TODO + /// + public IBsonSerializationDomain SerializationDomain + { + get => _serializationDomain; + set + { + if (_isFrozen) { ThrowFrozenException(); } + _serializationDomain = value; + } + } + // protected methods /// /// Creates a clone of the settings. diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index 1faed2df717..e29370f633d 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -44,7 +44,8 @@ private BsonDeserializationContext( _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; - _domain = domain ?? BsonSerializer.DefaultDomain; + _domain = domain; + //_domain = domain ?? BsonSerializer.DefaultDomain; //TODO This is to simplify finding errors } // public properties diff --git a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs index ad5bf481f4d..81000bc917b 100644 --- a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs @@ -336,7 +336,7 @@ public IBsonSerializer GetSerializer(IBsonSerializationDomain domain) } else { - _serializer = BsonSerializer.LookupSerializer(_memberType); //TODO ?? + _serializer = domain.LookupSerializer(_memberType); } } return _serializer; diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs index 8bce28575c5..2e11cc7320d 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs @@ -36,7 +36,7 @@ private BsonSerializationContext( { _writer = writer; _isDynamicType = isDynamicType; - _domain = domain ?? BsonSerializer.DefaultDomain; + _domain = writer.Settings.SerializationDomain ?? BsonSerializer.DefaultDomain; //TODO This is to simplify finding errors } // public properties @@ -114,7 +114,7 @@ public class Builder // private fields private Func _isDynamicType; private IBsonWriter _writer; - private IBsonSerializationDomain _domain; + private IBsonSerializationDomain _domain; //TODO Maybe we can remove this... // constructors internal Builder(BsonSerializationContext other, IBsonWriter writer) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index e1322be8133..76418cb927d 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -42,12 +42,15 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp private bool __useZeroIdChecker = false; // constructor - public BsonSerializationDomain() + public BsonSerializationDomain(string name = null) //TODO for testing { CreateSerializerRegistry(); RegisterIdGenerators(); + Name = name ?? "CUSTOM"; } + public string Name { get; private set; } + // public properties /// /// Gets the serializer registry. diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index 4590928edde..cea8aea6799 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -31,7 +31,7 @@ public static class BsonSerializer // static constructor static BsonSerializer() { - _domain = new BsonSerializationDomain(); + _domain = new BsonSerializationDomain("MAIN"); } /// diff --git a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs index e8e6e58b61d..c8925adc876 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs @@ -17,6 +17,7 @@ using System.Text; using MongoDB.Bson; using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders @@ -82,6 +83,10 @@ protected int? MaxWireDocumentSize } } + protected IBsonSerializationDomain SerializationDomain => + _encoderSettings.GetOrDefault(MessageEncoderSettingsName.SerializationDomain, + null); + // methods public BsonBinaryReader CreateBinaryReader() { @@ -102,6 +107,8 @@ public BsonBinaryWriter CreateBinaryWriter() writerSettings.Encoding = _encoderSettings.GetOrDefault(MessageEncoderSettingsName.WriteEncoding, writerSettings.Encoding); writerSettings.MaxDocumentSize = _encoderSettings.GetOrDefault(MessageEncoderSettingsName.MaxDocumentSize, writerSettings.MaxDocumentSize); writerSettings.MaxSerializationDepth = _encoderSettings.GetOrDefault(MessageEncoderSettingsName.MaxSerializationDepth, writerSettings.MaxSerializationDepth); + writerSettings.SerializationDomain = + _encoderSettings.GetOrDefault(MessageEncoderSettingsName.SerializationDomain, null); //TODO Using null here to find issues faster } return new BsonBinaryWriter(_stream, writerSettings); } diff --git a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs index 0a54dc96a30..a00362188a0 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs @@ -17,6 +17,7 @@ using System.IO; using MongoDB.Bson; using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver.Core.WireProtocol.Messages.Encoders.JsonEncoders @@ -37,6 +38,10 @@ protected MessageJsonEncoderBase(TextReader textReader, TextWriter textWriter, M _encoderSettings = encoderSettings; } + protected IBsonSerializationDomain SerializationDomain => + _encoderSettings.GetOrDefault(MessageEncoderSettingsName.SerializationDomain, + null); + // methods public JsonReader CreateJsonReader() { diff --git a/src/MongoDB.Driver/MongoClientSettings.cs b/src/MongoDB.Driver/MongoClientSettings.cs index d3123c0b2c5..d0c012adbbb 100644 --- a/src/MongoDB.Driver/MongoClientSettings.cs +++ b/src/MongoDB.Driver/MongoClientSettings.cs @@ -945,6 +945,7 @@ public MongoClientSettings Clone() clone._retryReads = _retryReads; clone._retryWrites = _retryWrites; clone._scheme = _scheme; + clone._serializationDomain = _serializationDomain; clone._serverApi = _serverApi; clone._servers = new List(_servers); clone._serverMonitoringMode = _serverMonitoringMode; diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs index a1286faf941..0232edd2b42 100644 --- a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -49,6 +49,7 @@ public void GeneralTest() { var customDomain = BsonSerializer.CreateDomain(); customDomain.RegisterSerializer(new CustomStringSerializer()); + var registered = customDomain.LookupSerializer(); var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = customDomain); var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); From 7628f317025d4a42612a18b6cad728f0de7ef5cc Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Thu, 30 Jan 2025 21:00:42 +0100 Subject: [PATCH 30/49] Small fixes --- src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs | 1 - .../ObjectModel/BsonDocumentWrapper.cs | 2 -- .../Serialization/BsonDeserializationContext.cs | 1 - .../Serialization/BsonSerializationContext.cs | 17 +++-------------- .../BinaryEncoders/MessageBinaryEncoderBase.cs | 4 ---- .../JsonEncoders/MessageJsonEncoderBase.cs | 6 ++---- .../MultipleRegistriesTests.cs | 6 +++--- 7 files changed, 8 insertions(+), 29 deletions(-) diff --git a/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs b/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs index a59c9372176..93da7f95a2d 100644 --- a/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs +++ b/src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs @@ -15,7 +15,6 @@ using System; using System.Text; -using MongoDB.Bson.Serialization; namespace MongoDB.Bson.IO { diff --git a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs index ed6d0f0e565..5a6eb642fee 100644 --- a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs +++ b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs @@ -188,8 +188,6 @@ public static IEnumerable CreateMultiple(Type nominalType, return values.Cast().Select(v => new BsonDocumentWrapper(v, serializer)); } - - // public methods /// /// Creates a shallow clone of the document (see also DeepClone). diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index e29370f633d..f08185af884 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -45,7 +45,6 @@ private BsonDeserializationContext( _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; _domain = domain; - //_domain = domain ?? BsonSerializer.DefaultDomain; //TODO This is to simplify finding errors } // public properties diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs index 2e11cc7320d..eedef3fea48 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs @@ -31,12 +31,11 @@ public class BsonSerializationContext // constructors private BsonSerializationContext( IBsonWriter writer, - Func isDynamicType, - IBsonSerializationDomain domain) + Func isDynamicType) { _writer = writer; _isDynamicType = isDynamicType; - _domain = writer.Settings.SerializationDomain ?? BsonSerializer.DefaultDomain; //TODO This is to simplify finding errors + _domain = writer.Settings.SerializationDomain ?? BsonSerializer.DefaultDomain; } // public properties @@ -114,7 +113,6 @@ public class Builder // private fields private Func _isDynamicType; private IBsonWriter _writer; - private IBsonSerializationDomain _domain; //TODO Maybe we can remove this... // constructors internal Builder(BsonSerializationContext other, IBsonWriter writer) @@ -137,15 +135,6 @@ internal Builder(BsonSerializationContext other, IBsonWriter writer) } } - /// - /// //TODO - /// - public IBsonSerializationDomain Domain - { - get => _domain; - set => _domain = value; - } - // properties /// /// Gets or sets the function used to determine if a type is a dynamic type. @@ -174,7 +163,7 @@ public IBsonWriter Writer /// A BsonSerializationContext. internal BsonSerializationContext Build() { - return new BsonSerializationContext(_writer, _isDynamicType, _domain); + return new BsonSerializationContext(_writer, _isDynamicType); } } } diff --git a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs index c8925adc876..8627e586689 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/MessageBinaryEncoderBase.cs @@ -83,10 +83,6 @@ protected int? MaxWireDocumentSize } } - protected IBsonSerializationDomain SerializationDomain => - _encoderSettings.GetOrDefault(MessageEncoderSettingsName.SerializationDomain, - null); - // methods public BsonBinaryReader CreateBinaryReader() { diff --git a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs index a00362188a0..94841a2a2ec 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/JsonEncoders/MessageJsonEncoderBase.cs @@ -38,10 +38,6 @@ protected MessageJsonEncoderBase(TextReader textReader, TextWriter textWriter, M _encoderSettings = encoderSettings; } - protected IBsonSerializationDomain SerializationDomain => - _encoderSettings.GetOrDefault(MessageEncoderSettingsName.SerializationDomain, - null); - // methods public JsonReader CreateJsonReader() { @@ -70,6 +66,8 @@ public JsonWriter CreateJsonWriter() writerSettings.NewLineChars = _encoderSettings.GetOrDefault(MessageEncoderSettingsName.NewLineChars, ""); writerSettings.OutputMode = _encoderSettings.GetOrDefault(MessageEncoderSettingsName.OutputMode, JsonOutputMode.Shell); writerSettings.ShellVersion = _encoderSettings.GetOrDefault(MessageEncoderSettingsName.ShellVersion, new Version(2, 6, 0)); + writerSettings.SerializationDomain = + _encoderSettings.GetOrDefault(MessageEncoderSettingsName.SerializationDomain, null); //TODO Using null here to find issues faster } return new JsonWriter(_textWriter, writerSettings); } diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs index 0232edd2b42..86dc9913081 100644 --- a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -27,8 +27,9 @@ public class MultipleRegistriesTests [Fact] public void GeneralTest() { + // At the moment having this uncommented would make the test fail due to the static caching of class maps // { - // var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = BsonSerializer.DefaultDomain); + // var client = DriverTestConfiguration.CreateMongoClient(); // var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); // db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); // var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); @@ -49,7 +50,6 @@ public void GeneralTest() { var customDomain = BsonSerializer.CreateDomain(); customDomain.RegisterSerializer(new CustomStringSerializer()); - var registered = customDomain.LookupSerializer(); var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = customDomain); var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); @@ -77,7 +77,7 @@ public class Person public int Age { get; set; } } - public class CustomStringSerializer : SealedClassSerializerBase + public class CustomStringSerializer : SealedClassSerializerBase //This serializer just adds "test" to any serialised string { /// public override int GetHashCode() => 0; From 3f5a047890c1b2f78a0845b67b8df82c2b9a7a87 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Thu, 30 Jan 2025 21:11:29 +0100 Subject: [PATCH 31/49] Some saving --- src/MongoDB.Bson/BsonExtensionMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MongoDB.Bson/BsonExtensionMethods.cs b/src/MongoDB.Bson/BsonExtensionMethods.cs index ec714b022a9..99768d23510 100644 --- a/src/MongoDB.Bson/BsonExtensionMethods.cs +++ b/src/MongoDB.Bson/BsonExtensionMethods.cs @@ -121,7 +121,7 @@ public static byte[] ToBson( { using (var bsonWriter = new BsonBinaryWriter(memoryStream, writerSettings ?? BsonBinaryWriterSettings.Defaults)) { - var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator).With(c => c.Domain = domain); + var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator); serializer.Serialize(context, args, obj); } return memoryStream.ToArray(); From 9ccfe7a9f8c4f83a8779549742959272590778b0 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:56:26 +0100 Subject: [PATCH 32/49] Naming correction --- .../Serialization/BsonSerializationDomain.cs | 154 +++++++++--------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 76418cb927d..fef7c5b2669 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -18,28 +18,28 @@ namespace MongoDB.Bson.Serialization internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisposable { // private fields - private ReaderWriterLockSlim __configLock = + private ReaderWriterLockSlim _configLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); - private Dictionary __idGenerators = new Dictionary(); + private Dictionary _idGenerators = new Dictionary(); - private Dictionary __discriminatorConventions = + private Dictionary _discriminatorConventions = new Dictionary(); - private Dictionary> __discriminators = + private Dictionary> _discriminators = new Dictionary>(); - private HashSet __discriminatedTypes = new HashSet(); - private BsonSerializerRegistry __serializerRegistry; + private HashSet _discriminatedTypes = new HashSet(); + private BsonSerializerRegistry _serializerRegistry; - private TypeMappingSerializationProvider __typeMappingSerializationProvider; + private TypeMappingSerializationProvider _typeMappingSerializationProvider; // ConcurrentDictionary is being used as a concurrent set of Type. The values will always be null. - private ConcurrentDictionary __typesWithRegisteredKnownTypes = + private ConcurrentDictionary _typesWithRegisteredKnownTypes = new ConcurrentDictionary(); - private bool __useNullIdChecker = false; - private bool __useZeroIdChecker = false; + private bool _useNullIdChecker = false; + private bool _useZeroIdChecker = false; // constructor public BsonSerializationDomain(string name = null) //TODO for testing @@ -57,7 +57,7 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp /// public IBsonSerializerRegistry SerializerRegistry { - get { return __serializerRegistry; } + get { return _serializerRegistry; } } /// @@ -65,8 +65,8 @@ public IBsonSerializerRegistry SerializerRegistry /// public bool UseNullIdChecker { - get { return __useNullIdChecker; } - set { __useNullIdChecker = value; } + get { return _useNullIdChecker; } + set { _useNullIdChecker = value; } } public bool UseNullIdCheckerEnabled => UseNullIdChecker; @@ -76,8 +76,8 @@ public bool UseNullIdChecker /// public bool UseZeroIdChecker { - get { return __useZeroIdChecker; } - set { __useZeroIdChecker = value; } + get { return _useZeroIdChecker; } + set { _useZeroIdChecker = value; } } public bool UseZeroIdCheckerEnabled => UseZeroIdChecker; @@ -85,7 +85,7 @@ public bool UseZeroIdChecker // internal properties public ReaderWriterLockSlim ConfigLock { - get { return __configLock; } + get { return _configLock; } } /// @@ -283,23 +283,23 @@ public object Deserialize(TextReader textReader, Type nominalType, public IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, IDiscriminatorConvention discriminatorConvention) { - __configLock.EnterReadLock(); + _configLock.EnterReadLock(); try { - if (__discriminatorConventions.TryGetValue(type, out var registeredDiscriminatorConvention)) + if (_discriminatorConventions.TryGetValue(type, out var registeredDiscriminatorConvention)) { return registeredDiscriminatorConvention; } } finally { - __configLock.ExitReadLock(); + _configLock.ExitReadLock(); } - __configLock.EnterWriteLock(); + _configLock.EnterWriteLock(); try { - if (__discriminatorConventions.TryGetValue(type, out var registeredDiscrimantorConvention)) + if (_discriminatorConventions.TryGetValue(type, out var registeredDiscrimantorConvention)) { return registeredDiscrimantorConvention; } @@ -309,20 +309,20 @@ public IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, } finally { - __configLock.ExitWriteLock(); + _configLock.ExitWriteLock(); } } public bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) { - __configLock.EnterReadLock(); + _configLock.EnterReadLock(); try { - return __discriminatorConventions.ContainsKey(type); + return _discriminatorConventions.ContainsKey(type); } finally { - __configLock.ExitReadLock(); + _configLock.ExitReadLock(); } } @@ -334,7 +334,7 @@ public bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) public bool IsTypeDiscriminated(Type type) { var typeInfo = type.GetTypeInfo(); - return typeInfo.IsInterface || __discriminatedTypes.Contains(type); + return typeInfo.IsInterface || _discriminatedTypes.Contains(type); } /// @@ -353,14 +353,14 @@ public Type LookupActualType(Type nominalType, BsonValue discriminator) // note: EnsureKnownTypesAreRegistered handles its own locking so call from outside any lock EnsureKnownTypesAreRegistered(nominalType); - __configLock.EnterReadLock(); + _configLock.EnterReadLock(); try { Type actualType = null; HashSet hashSet; var nominalTypeInfo = nominalType.GetTypeInfo(); - if (__discriminators.TryGetValue(discriminator, out hashSet)) + if (_discriminators.TryGetValue(discriminator, out hashSet)) { foreach (var type in hashSet) { @@ -408,7 +408,7 @@ public Type LookupActualType(Type nominalType, BsonValue discriminator) } finally { - __configLock.ExitReadLock(); + _configLock.ExitReadLock(); } } @@ -419,25 +419,25 @@ public Type LookupActualType(Type nominalType, BsonValue discriminator) /// A discriminator convention. public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) { - __configLock.EnterReadLock(); + _configLock.EnterReadLock(); try { IDiscriminatorConvention convention; - if (__discriminatorConventions.TryGetValue(type, out convention)) + if (_discriminatorConventions.TryGetValue(type, out convention)) { return convention; } } finally { - __configLock.ExitReadLock(); + _configLock.ExitReadLock(); } - __configLock.EnterWriteLock(); + _configLock.EnterWriteLock(); try { IDiscriminatorConvention convention; - if (!__discriminatorConventions.TryGetValue(type, out convention)) + if (!_discriminatorConventions.TryGetValue(type, out convention)) { var typeInfo = type.GetTypeInfo(); if (type == typeof(object)) @@ -465,7 +465,7 @@ public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) break; } - if (__discriminatorConventions.TryGetValue(parentType, out convention)) + if (_discriminatorConventions.TryGetValue(parentType, out convention)) { break; } @@ -487,7 +487,7 @@ public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) } finally { - __configLock.ExitWriteLock(); + _configLock.ExitWriteLock(); } } @@ -498,28 +498,28 @@ public IDiscriminatorConvention LookupDiscriminatorConvention(Type type) /// An IdGenerator for the Id type. public IIdGenerator LookupIdGenerator(Type type) { - __configLock.EnterReadLock(); + _configLock.EnterReadLock(); try { IIdGenerator idGenerator; - if (__idGenerators.TryGetValue(type, out idGenerator)) + if (_idGenerators.TryGetValue(type, out idGenerator)) { return idGenerator; } } finally { - __configLock.ExitReadLock(); + _configLock.ExitReadLock(); } - __configLock.EnterWriteLock(); + _configLock.EnterWriteLock(); try { IIdGenerator idGenerator; - if (!__idGenerators.TryGetValue(type, out idGenerator)) + if (!_idGenerators.TryGetValue(type, out idGenerator)) { var typeInfo = type.GetTypeInfo(); - if (typeInfo.IsValueType && __useZeroIdChecker) + if (typeInfo.IsValueType && _useZeroIdChecker) { var iEquatableDefinition = typeof(IEquatable<>); var iEquatableType = iEquatableDefinition.MakeGenericType(type); @@ -530,7 +530,7 @@ public IIdGenerator LookupIdGenerator(Type type) idGenerator = (IIdGenerator)Activator.CreateInstance(zeroIdCheckerType); } } - else if (__useNullIdChecker) + else if (_useNullIdChecker) { idGenerator = NullIdChecker.Instance; } @@ -539,14 +539,14 @@ public IIdGenerator LookupIdGenerator(Type type) idGenerator = null; } - __idGenerators[type] = idGenerator; // remember it even if it's null + _idGenerators[type] = idGenerator; // remember it even if it's null } return idGenerator; } finally { - __configLock.ExitWriteLock(); + _configLock.ExitWriteLock(); } } @@ -567,7 +567,7 @@ public IBsonSerializer LookupSerializer() /// A serializer for the Type. public IBsonSerializer LookupSerializer(Type type) { - return __serializerRegistry.GetSerializer(type); + return _serializerRegistry.GetSerializer(type); } /// @@ -585,14 +585,14 @@ public void RegisterDiscriminator(Type type, BsonValue discriminator) throw new BsonSerializationException(message); } - __configLock.EnterWriteLock(); + _configLock.EnterWriteLock(); try { HashSet hashSet; - if (!__discriminators.TryGetValue(discriminator, out hashSet)) + if (!_discriminators.TryGetValue(discriminator, out hashSet)) { hashSet = new HashSet(); - __discriminators.Add(discriminator, hashSet); + _discriminators.Add(discriminator, hashSet); } if (!hashSet.Contains(type)) @@ -602,13 +602,13 @@ public void RegisterDiscriminator(Type type, BsonValue discriminator) // mark all base types as discriminated (so we know that it's worth reading a discriminator) for (var baseType = typeInfo.BaseType; baseType != null; baseType = baseType.GetTypeInfo().BaseType) { - __discriminatedTypes.Add(baseType); + _discriminatedTypes.Add(baseType); } } } finally { - __configLock.ExitWriteLock(); + _configLock.ExitWriteLock(); } } @@ -619,12 +619,12 @@ public void RegisterDiscriminator(Type type, BsonValue discriminator) /// The discriminator convention. public void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention) { - __configLock.EnterWriteLock(); + _configLock.EnterWriteLock(); try { - if (!__discriminatorConventions.ContainsKey(type)) + if (!_discriminatorConventions.ContainsKey(type)) { - __discriminatorConventions.Add(type, convention); + _discriminatorConventions.Add(type, convention); } else { @@ -635,7 +635,7 @@ public void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention } finally { - __configLock.ExitWriteLock(); + _configLock.ExitWriteLock(); } } @@ -648,7 +648,7 @@ public void RegisterGenericSerializerDefinition( Type genericTypeDefinition, Type genericSerializerDefinition) { - __typeMappingSerializationProvider.RegisterMapping(genericTypeDefinition, genericSerializerDefinition); + _typeMappingSerializationProvider.RegisterMapping(genericTypeDefinition, genericSerializerDefinition); } /// @@ -658,14 +658,14 @@ public void RegisterGenericSerializerDefinition( /// The IdGenerator for the Id Type. public void RegisterIdGenerator(Type type, IIdGenerator idGenerator) { - __configLock.EnterWriteLock(); + _configLock.EnterWriteLock(); try { - __idGenerators[type] = idGenerator; + _idGenerators[type] = idGenerator; } finally { - __configLock.ExitWriteLock(); + _configLock.ExitWriteLock(); } } @@ -675,7 +675,7 @@ public void RegisterIdGenerator(Type type, IIdGenerator idGenerator) /// The serialization provider. public void RegisterSerializationProvider(IBsonSerializationProvider provider) { - __serializerRegistry.RegisterSerializationProvider(provider); + _serializerRegistry.RegisterSerializationProvider(provider); } /// @@ -695,7 +695,7 @@ public void RegisterSerializer(IBsonSerializer serializer) /// The serializer. public void RegisterSerializer(Type type, IBsonSerializer serializer) { - __serializerRegistry.RegisterSerializer(type, serializer); + _serializerRegistry.RegisterSerializer(type, serializer); } /// @@ -747,7 +747,7 @@ public void Serialize( /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. public bool TryRegisterSerializer(Type type, IBsonSerializer serializer) { - return __serializerRegistry.TryRegisterSerializer(type, serializer); + return _serializerRegistry.TryRegisterSerializer(type, serializer); } /// @@ -764,15 +764,15 @@ public bool TryRegisterSerializer(IBsonSerializer serializer) // internal methods public void EnsureKnownTypesAreRegistered(Type nominalType) { - if (__typesWithRegisteredKnownTypes.ContainsKey(nominalType)) + if (_typesWithRegisteredKnownTypes.ContainsKey(nominalType)) { return; } - __configLock.EnterWriteLock(); + _configLock.EnterWriteLock(); try { - if (!__typesWithRegisteredKnownTypes.ContainsKey(nominalType)) + if (!_typesWithRegisteredKnownTypes.ContainsKey(nominalType)) { // only call LookupClassMap for classes with a BsonKnownTypesAttribute var hasKnownTypesAttribute = nominalType.GetTypeInfo() @@ -786,34 +786,34 @@ public void EnsureKnownTypesAreRegistered(Type nominalType) // NOTE: The nominalType MUST be added to __typesWithRegisteredKnownTypes after all registration // work is done to ensure that other threads don't access a partially registered nominalType // when performing the initial check above outside the __config lock. - __typesWithRegisteredKnownTypes[nominalType] = null; + _typesWithRegisteredKnownTypes[nominalType] = null; } } finally { - __configLock.ExitWriteLock(); + _configLock.ExitWriteLock(); } } public void Dispose() { - __configLock.Dispose(); + _configLock.Dispose(); } // private methods private void CreateSerializerRegistry() { - __serializerRegistry = new BsonSerializerRegistry(); - __typeMappingSerializationProvider = new TypeMappingSerializationProvider(); + _serializerRegistry = new BsonSerializerRegistry(); + _typeMappingSerializationProvider = new TypeMappingSerializationProvider(); // order matters. It's in reverse order of how they'll get consumed - __serializerRegistry.RegisterSerializationProvider(new BsonClassMapSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new DiscriminatedInterfaceSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new CollectionsSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new PrimitiveSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(new AttributedSerializationProvider()); - __serializerRegistry.RegisterSerializationProvider(__typeMappingSerializationProvider); - __serializerRegistry.RegisterSerializationProvider(new BsonObjectModelSerializationProvider()); + _serializerRegistry.RegisterSerializationProvider(new BsonClassMapSerializationProvider()); + _serializerRegistry.RegisterSerializationProvider(new DiscriminatedInterfaceSerializationProvider()); + _serializerRegistry.RegisterSerializationProvider(new CollectionsSerializationProvider()); + _serializerRegistry.RegisterSerializationProvider(new PrimitiveSerializationProvider()); + _serializerRegistry.RegisterSerializationProvider(new AttributedSerializationProvider()); + _serializerRegistry.RegisterSerializationProvider(_typeMappingSerializationProvider); + _serializerRegistry.RegisterSerializationProvider(new BsonObjectModelSerializationProvider()); } private void RegisterIdGenerators() From d3973e18e761657e12c5695ca20b7d340825f4a1 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:56:37 +0100 Subject: [PATCH 33/49] Added test and removed comment --- src/MongoDB.Bson/Serialization/BsonClassMap.cs | 2 +- tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 5bb56d12315..4958d1ea614 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -32,7 +32,7 @@ namespace MongoDB.Bson.Serialization public class BsonClassMap { // private static fields - private readonly static Dictionary __classMaps = new Dictionary(); //TODO I think the static fields and methods should not be here, but on the domain + private readonly static Dictionary __classMaps = new Dictionary(); private readonly static Queue __knownTypesQueue = new Queue(); private static int __freezeNestingLevel = 0; diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs index 86dc9913081..7c72a0d725c 100644 --- a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -61,12 +61,15 @@ public void GeneralTest() var person = new Person { Id = ObjectId.Parse("6797b56bf5495bf53aa3078f"), Name = "Mario", Age = 24 }; collection.InsertOne(person); - var retrieved = bsonCollection.FindSync("{}").ToList().Single(); - var toString = retrieved.ToString(); + var retrievedAsBson = bsonCollection.FindSync("{}").ToList().Single(); + var toString = retrievedAsBson.ToString(); var expectedVal = """{ "_id" : { "$oid" : "6797b56bf5495bf53aa3078f" }, "Name" : "Mariotest", "Age" : 24 }"""; Assert.Equal(expectedVal, toString); + + var retrievedTyped = collection.FindSync("{}").ToList().Single(); + Assert.Equal("Mario", retrievedTyped.Name); } } @@ -89,8 +92,7 @@ protected override string DeserializeValue(BsonDeserializationContext context, B var bsonType = bsonReader.GetCurrentBsonType(); return bsonType switch { - BsonType.String => bsonReader.ReadString(), - BsonType.Symbol => bsonReader.ReadSymbol(), + BsonType.String => bsonReader.ReadString().Replace("test", ""), _ => throw CreateCannotDeserializeFromBsonTypeException(bsonType) }; } From a587d6dcb43eda147de61d556ee02ecf097c7d15 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 3 Feb 2025 10:16:57 +0100 Subject: [PATCH 34/49] Improved tests --- .../Serializers/BsonClassMapSerializer.cs | 2 +- .../MultipleRegistriesTests.cs | 35 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs index 6eff0f30971..9ef3c9acf49 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs @@ -571,7 +571,7 @@ private object DeserializeMemberValue(BsonDeserializationContext context, BsonMe { try { - return memberMap.GetSerializer().Deserialize(context); + return memberMap.GetSerializer(context.Domain).Deserialize(context); } catch (Exception ex) { diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs index 7c72a0d725c..ee0aec1b593 100644 --- a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -25,7 +25,7 @@ namespace MongoDB.Driver.Tests public class MultipleRegistriesTests { [Fact] - public void GeneralTest() + public void TestSerialization() { // At the moment having this uncommented would make the test fail due to the static caching of class maps // { @@ -73,6 +73,32 @@ public void GeneralTest() } } + [Fact] + public void TestDeserialization() + { + { + var client = DriverTestConfiguration.CreateMongoClient(); + var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); + db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + + var person = new Person1 { Id = ObjectId.Parse("6797b56bf5495bf53aa3078f"), Name = "Mariotest", Age = 24 }; + collection.InsertOne(person); + } + + { + var customDomain = BsonSerializer.CreateDomain(); + customDomain.RegisterSerializer(new CustomStringSerializer()); + + var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = customDomain); + var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); + var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + + var retrievedTyped = collection.FindSync("{}").ToList().Single(); + Assert.Equal("Mario", retrievedTyped.Name); + } + } + public class Person { [BsonId] public ObjectId Id { get; set; } @@ -80,6 +106,13 @@ public class Person public int Age { get; set; } } + public class Person1 + { + [BsonId] public ObjectId Id { get; set; } + public string Name { get; set; } + public int Age { get; set; } + } + public class CustomStringSerializer : SealedClassSerializerBase //This serializer just adds "test" to any serialised string { /// From 856cfb87eeb6895ca48874510de9858856b48c73 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 3 Feb 2025 13:44:40 +0100 Subject: [PATCH 35/49] Improved deserialization to work as serialization --- .../IO/BsonBinaryReaderSettings.cs | 3 ++- .../IO/BsonDocumentReaderSettings.cs | 2 +- src/MongoDB.Bson/IO/BsonReaderSettings.cs | 15 +++++++++++++++ src/MongoDB.Bson/IO/IBsonReader.cs | 7 ++++++- src/MongoDB.Bson/IO/JsonReaderSettings.cs | 2 +- .../BsonDeserializationContext.cs | 18 +++--------------- .../Serialization/BsonSerializationDomain.cs | 16 ++++++---------- .../CursorBatchDeserializationHelper.cs | 2 ++ 8 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs b/src/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs index 72305ed0169..7d10322db70 100644 --- a/src/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs +++ b/src/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs @@ -136,7 +136,8 @@ protected override BsonReaderSettings CloneImplementation() Encoding = _encoding, FixOldBinarySubTypeOnInput = _fixOldBinarySubTypeOnInput, FixOldDateTimeMaxValueOnInput = _fixOldDateTimeMaxValueOnInput, - MaxDocumentSize = _maxDocumentSize + MaxDocumentSize = _maxDocumentSize, + SerializationDomain = SerializationDomain, //TODO This can be improved }; return clone; diff --git a/src/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs b/src/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs index 3b87c603ffd..b1d78974a3a 100644 --- a/src/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs +++ b/src/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs @@ -67,7 +67,7 @@ public static BsonDocumentReaderSettings Defaults /// A clone of the settings. protected override BsonReaderSettings CloneImplementation() { - var clone = new BsonDocumentReaderSettings(); + var clone = new BsonDocumentReaderSettings { SerializationDomain = SerializationDomain }; //TODO This can be improved return clone; } } diff --git a/src/MongoDB.Bson/IO/BsonReaderSettings.cs b/src/MongoDB.Bson/IO/BsonReaderSettings.cs index 649c02ff59c..36b7fc1e58e 100644 --- a/src/MongoDB.Bson/IO/BsonReaderSettings.cs +++ b/src/MongoDB.Bson/IO/BsonReaderSettings.cs @@ -14,6 +14,7 @@ */ using System; +using MongoDB.Bson.Serialization; namespace MongoDB.Bson.IO { @@ -24,6 +25,7 @@ public abstract class BsonReaderSettings { // private fields private bool _isFrozen; + private IBsonSerializationDomain _serializationDomain; // constructors /// @@ -77,6 +79,19 @@ public BsonReaderSettings FrozenCopy() } } + /// + /// //TODO + /// + public IBsonSerializationDomain SerializationDomain + { + get => _serializationDomain; + set + { + if (_isFrozen) { ThrowFrozenException(); } + _serializationDomain = value; + } + } + // protected methods /// /// Creates a clone of the settings. diff --git a/src/MongoDB.Bson/IO/IBsonReader.cs b/src/MongoDB.Bson/IO/IBsonReader.cs index 14af4722a33..68963dcab7d 100644 --- a/src/MongoDB.Bson/IO/IBsonReader.cs +++ b/src/MongoDB.Bson/IO/IBsonReader.cs @@ -62,7 +62,7 @@ public interface IBsonReader : IDisposable /// /// Pops the settings. /// - void PopSettings(); + void PopSettings(); //TODO Why do we have push and pop methods? They are not used /// /// Pushes new settings for the reader. @@ -246,6 +246,11 @@ public interface IBsonReader : IDisposable /// The bookmark. void ReturnToBookmark(BsonReaderBookmark bookmark); + /// + /// Gets the settings of the reader. + /// + BsonReaderSettings Settings { get; } + /// /// Skips the name (reader must be positioned on a name). /// diff --git a/src/MongoDB.Bson/IO/JsonReaderSettings.cs b/src/MongoDB.Bson/IO/JsonReaderSettings.cs index 383d4f7271f..f44b0e1000e 100644 --- a/src/MongoDB.Bson/IO/JsonReaderSettings.cs +++ b/src/MongoDB.Bson/IO/JsonReaderSettings.cs @@ -68,7 +68,7 @@ public static JsonReaderSettings Defaults /// A clone of the settings. protected override BsonReaderSettings CloneImplementation() { - var clone = new JsonReaderSettings(); + var clone = new JsonReaderSettings { SerializationDomain = SerializationDomain }; //TODO This can be improved return clone; } } diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index f08185af884..a33d5a62a1c 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -15,8 +15,6 @@ using System; using MongoDB.Bson.IO; -using MongoDB.Bson.Serialization.Options; -using MongoDB.Bson.Serialization.Serializers; namespace MongoDB.Bson.Serialization { @@ -37,14 +35,13 @@ private BsonDeserializationContext( IBsonReader reader, bool allowDuplicateElementNames, IBsonSerializer dynamicArraySerializer, - IBsonSerializer dynamicDocumentSerializer, - IBsonSerializationDomain domain) + IBsonSerializer dynamicDocumentSerializer) { _reader = reader; _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; - _domain = domain; + _domain = reader.Settings.SerializationDomain ?? BsonSerializer.DefaultDomain; } // public properties @@ -221,15 +218,6 @@ public IBsonReader Reader get { return _reader; } } - /// - /// //TODO - /// - public IBsonSerializationDomain Domain - { - get => _domain; - set => _domain = value; - } - // public methods /// /// Builds the BsonDeserializationContext instance. @@ -237,7 +225,7 @@ public IBsonSerializationDomain Domain /// A BsonDeserializationContext. internal BsonDeserializationContext Build() { - return new BsonDeserializationContext(_reader, _allowDuplicateElementNames, _dynamicArraySerializer, _dynamicDocumentSerializer, _domain); + return new BsonDeserializationContext(_reader, _allowDuplicateElementNames, _dynamicArraySerializer, _dynamicDocumentSerializer); } } } diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index fef7c5b2669..0ece09237a4 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -18,25 +18,21 @@ namespace MongoDB.Bson.Serialization internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisposable { // private fields - private ReaderWriterLockSlim _configLock = - new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + private ReaderWriterLockSlim _configLock = new(LockRecursionPolicy.SupportsRecursion); - private Dictionary _idGenerators = new Dictionary(); + private Dictionary _idGenerators = new(); - private Dictionary _discriminatorConventions = - new Dictionary(); + private Dictionary _discriminatorConventions = new(); - private Dictionary> _discriminators = - new Dictionary>(); + private Dictionary> _discriminators = new(); - private HashSet _discriminatedTypes = new HashSet(); + private HashSet _discriminatedTypes = new(); private BsonSerializerRegistry _serializerRegistry; private TypeMappingSerializationProvider _typeMappingSerializationProvider; // ConcurrentDictionary is being used as a concurrent set of Type. The values will always be null. - private ConcurrentDictionary _typesWithRegisteredKnownTypes = - new ConcurrentDictionary(); + private ConcurrentDictionary _typesWithRegisteredKnownTypes = new(); private bool _useNullIdChecker = false; private bool _useZeroIdChecker = false; diff --git a/src/MongoDB.Driver/Core/Operations/CursorBatchDeserializationHelper.cs b/src/MongoDB.Driver/Core/Operations/CursorBatchDeserializationHelper.cs index 27ff4252dc0..6fa3bd744a3 100644 --- a/src/MongoDB.Driver/Core/Operations/CursorBatchDeserializationHelper.cs +++ b/src/MongoDB.Driver/Core/Operations/CursorBatchDeserializationHelper.cs @@ -44,6 +44,8 @@ public static List DeserializeBatch(RawBsonArray batch, IB if (messageEncoderSettings != null) { readerSettings.Encoding = messageEncoderSettings.GetOrDefault(MessageEncoderSettingsName.ReadEncoding, Utf8Encodings.Strict); + readerSettings.SerializationDomain = + messageEncoderSettings.GetOrDefault(MessageEncoderSettingsName.SerializationDomain, null); }; using (var stream = new ByteBufferStream(batch.Slice, ownsBuffer: false)) From 2cc6a8d88133cb58e9765c895291c48a4e10a70e Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 4 Feb 2025 10:52:25 +0100 Subject: [PATCH 36/49] Trying to fix class map --- .../Serialization/BsonClassMap.cs | 237 ++--------- .../Serialization/BsonSerializationDomain.cs | 11 +- .../Serialization/IBsonClassMapDomain.cs | 383 ++++++++++++++++++ .../Serialization/IBsonSerializationDomain.cs | 12 +- 4 files changed, 439 insertions(+), 204 deletions(-) create mode 100644 src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 4958d1ea614..ea6dcaa0771 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -31,11 +31,6 @@ namespace MongoDB.Bson.Serialization /// public class BsonClassMap { - // private static fields - private readonly static Dictionary __classMaps = new Dictionary(); - private readonly static Queue __knownTypesQueue = new Queue(); - private static int __freezeNestingLevel = 0; - // private fields private readonly Type _classType; private readonly List _creatorMaps; @@ -282,103 +277,32 @@ public static Type GetMemberInfoType(MemberInfo memberInfo) /// Gets all registered class maps. /// /// All registered class maps. - public static IEnumerable GetRegisteredClassMaps() - { - BsonSerializer.ConfigLock.EnterReadLock(); //TODO It would make sense to look at this after the PR by Robert is merged - try - { - return __classMaps.Values.ToList(); // return a copy for thread safety - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - } + public static IEnumerable GetRegisteredClassMaps() => + BsonSerializer.DefaultDomain.ClassMapDomain.GetRegisteredClassMaps(); /// /// Checks whether a class map is registered for a type. /// /// The type to check. /// True if there is a class map registered for the type. - public static bool IsClassMapRegistered(Type type) - { - if (type == null) - { - throw new ArgumentNullException("type"); - } - - BsonSerializer.ConfigLock.EnterReadLock(); - try - { - return __classMaps.ContainsKey(type); - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - } + public static bool IsClassMapRegistered(Type type) => + BsonSerializer.DefaultDomain.ClassMapDomain.IsClassMapRegistered(type); /// /// Looks up a class map (will AutoMap the class if no class map is registered). /// /// The class type. /// The class map. - public static BsonClassMap LookupClassMap(Type classType) - { - if (classType == null) - { - throw new ArgumentNullException("classType"); - } - - BsonSerializer.ConfigLock.EnterReadLock(); - try - { - if (__classMaps.TryGetValue(classType, out var classMap)) - { - if (classMap.IsFrozen) - { - return classMap; - } - } - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - - // automatically create a new classMap for classType and register it (unless another thread does first) - // do the work of speculatively creating a new class map outside of holding any lock - var classMapDefinition = typeof(BsonClassMap<>); - var classMapType = classMapDefinition.MakeGenericType(classType); - var newClassMap = (BsonClassMap)Activator.CreateInstance(classMapType); - newClassMap.AutoMap(); - - BsonSerializer.ConfigLock.EnterWriteLock(); - try - { - if (!__classMaps.TryGetValue(classType, out var classMap)) - { - RegisterClassMap(newClassMap); - classMap = newClassMap; - } - - return classMap.Freeze(); - } - finally - { - BsonSerializer.ConfigLock.ExitWriteLock(); - } - } + public static BsonClassMap LookupClassMap(Type classType) => + BsonSerializer.DefaultDomain.ClassMapDomain.LookupClassMap(classType); /// /// Creates and registers a class map. /// /// The class. /// The class map. - public static BsonClassMap RegisterClassMap() //TODO We should move the static methods here to IBSonSerializerDomain - { - return RegisterClassMap(cm => { cm.AutoMap(); }); - } + public static BsonClassMap RegisterClassMap()=> + BsonSerializer.DefaultDomain.ClassMapDomain.RegisterClassMap(); /// /// Creates and registers a class map. @@ -387,35 +311,14 @@ public static BsonClassMap RegisterClassMap() //TODO We should /// The class map initializer. /// The class map. public static BsonClassMap RegisterClassMap(Action> classMapInitializer) - { - var classMap = new BsonClassMap(classMapInitializer); - RegisterClassMap(classMap); - return classMap; - } + => BsonSerializer.DefaultDomain.ClassMapDomain.RegisterClassMap(classMapInitializer); /// /// Registers a class map. /// /// The class map. public static void RegisterClassMap(BsonClassMap classMap) - { - if (classMap == null) - { - throw new ArgumentNullException("classMap"); - } - - BsonSerializer.ConfigLock.EnterWriteLock(); - try - { - // note: class maps can NOT be replaced (because derived classes refer to existing instance) - __classMaps.Add(classMap.ClassType, classMap); - BsonSerializer.RegisterDiscriminator(classMap.ClassType, classMap.Discriminator); - } - finally - { - BsonSerializer.ConfigLock.ExitWriteLock(); - } - } + => BsonSerializer.DefaultDomain.ClassMapDomain.RegisterClassMap(classMap); /// /// Registers a class map if it is not already registered. @@ -423,16 +326,7 @@ public static void RegisterClassMap(BsonClassMap classMap) /// The class. /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap() - { - return TryRegisterClassMap(ClassMapFactory); - - static BsonClassMap ClassMapFactory() - { - var classMap = new BsonClassMap(); - classMap.AutoMap(); - return classMap; - } - } + => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(); /// /// Registers a class map if it is not already registered. @@ -441,19 +335,7 @@ static BsonClassMap ClassMapFactory() /// The class map. /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap(BsonClassMap classMap) - { - if (classMap == null) - { - throw new ArgumentNullException(nameof(classMap)); - } - - return TryRegisterClassMap(ClassMapFactory); - - BsonClassMap ClassMapFactory() - { - return classMap; - } - } + => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(classMap); /// /// Registers a class map if it is not already registered. @@ -462,19 +344,7 @@ BsonClassMap ClassMapFactory() /// The class map initializer (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap(Action> classMapInitializer) - { - if (classMapInitializer == null) - { - throw new ArgumentNullException(nameof(classMapInitializer)); - } - - return TryRegisterClassMap(ClassMapFactory); - - BsonClassMap ClassMapFactory() - { - return new BsonClassMap(classMapInitializer); - } - } + => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(classMapInitializer); /// /// Registers a class map if it is not already registered. @@ -483,45 +353,7 @@ BsonClassMap ClassMapFactory() /// The class map factory (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap(Func> classMapFactory) - { - if (classMapFactory == null) - { - throw new ArgumentNullException(nameof(classMapFactory)); - } - - BsonSerializer.ConfigLock.EnterReadLock(); - try - { - if (__classMaps.ContainsKey(typeof(TClass))) - { - return false; - } - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - - BsonSerializer.ConfigLock.EnterWriteLock(); - try - { - if (__classMaps.ContainsKey(typeof(TClass))) - { - return false; - } - else - { - // create a classMap for TClass and register it - var classMap = classMapFactory(); - RegisterClassMap(classMap); - return true; - } - } - finally - { - BsonSerializer.ConfigLock.ExitWriteLock(); - } - } + => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(classMapFactory); // public methods /// @@ -573,13 +405,30 @@ obj is BsonClassMap other && /// public override int GetHashCode() => 0; + internal class FreezeContext + { + public int FreezeNestingLevel { get; set; } = 0; + public Queue KnownTypesQueue { get; set; } = new(); + public IBsonSerializationDomain SerializationDomain { get; set; } + } + /// /// Freezes the class map. /// /// The frozen class map. - public BsonClassMap Freeze() + public BsonClassMap Freeze() => Freeze(BsonSerializer.DefaultDomain); + + + internal BsonClassMap Freeze(IBsonSerializationDomain domain) + { + var freezeContext = new FreezeContext() { SerializationDomain = domain }; + return Freeze(freezeContext); + } + + private BsonClassMap Freeze(FreezeContext context) { - BsonSerializer.ConfigLock.EnterReadLock(); + var configLock = (context.SerializationDomain as IBsonSerializationDomainInternal)!.ConfigLock; + configLock.EnterReadLock(); try { if (_frozen) @@ -589,15 +438,15 @@ public BsonClassMap Freeze() } finally { - BsonSerializer.ConfigLock.ExitReadLock(); + configLock.ExitReadLock(); } - BsonSerializer.ConfigLock.EnterWriteLock(); + configLock.EnterWriteLock(); try { if (!_frozen) { - __freezeNestingLevel++; + context.FreezeNestingLevel++; try { var baseType = _classType.GetTypeInfo().BaseType; @@ -607,7 +456,7 @@ public BsonClassMap Freeze() { _baseClassMap = LookupClassMap(baseType); } - _baseClassMap.Freeze(); + _baseClassMap.Freeze(context); //TODO This is not necessary, because LookupClassMap will only return a frozen class map _discriminatorIsRequired |= _baseClassMap._discriminatorIsRequired; _hasRootClass |= (_isRootClass || _baseClassMap.HasRootClass); _allMemberMaps.AddRange(_baseClassMap.AllMemberMaps); @@ -699,28 +548,28 @@ public BsonClassMap Freeze() // this avoids infinite recursion when going back down the inheritance tree while processing known types foreach (var knownType in _knownTypes) { - __knownTypesQueue.Enqueue(knownType); + context.KnownTypesQueue.Enqueue(knownType); } // if we are back to the first level go ahead and process any queued known types - if (__freezeNestingLevel == 1) + if (context.FreezeNestingLevel == 1) { - while (__knownTypesQueue.Count != 0) + while (context.KnownTypesQueue.Count != 0) { - var knownType = __knownTypesQueue.Dequeue(); + var knownType = context.KnownTypesQueue.Dequeue(); LookupClassMap(knownType); // will AutoMap and/or Freeze knownType if necessary } } } finally { - __freezeNestingLevel--; + context.FreezeNestingLevel--; } } } finally { - BsonSerializer.ConfigLock.ExitWriteLock(); + configLock.ExitWriteLock(); } return this; } diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 0ece09237a4..ccf91bc7647 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -19,16 +19,12 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp { // private fields private ReaderWriterLockSlim _configLock = new(LockRecursionPolicy.SupportsRecursion); - + private IBsonClassMapDomain _classMapDomain; private Dictionary _idGenerators = new(); - private Dictionary _discriminatorConventions = new(); - private Dictionary> _discriminators = new(); - private HashSet _discriminatedTypes = new(); private BsonSerializerRegistry _serializerRegistry; - private TypeMappingSerializationProvider _typeMappingSerializationProvider; // ConcurrentDictionary is being used as a concurrent set of Type. The values will always be null. @@ -38,10 +34,11 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp private bool _useZeroIdChecker = false; // constructor - public BsonSerializationDomain(string name = null) //TODO for testing + public BsonSerializationDomain(string name = null) //TODO name is used for testing { CreateSerializerRegistry(); RegisterIdGenerators(); + _classMapDomain = new BsonClassMapDomain(); Name = name ?? "CUSTOM"; } @@ -735,6 +732,8 @@ public void Serialize( serializer.Serialize(context, args, value); } + public IBsonClassMapDomain ClassMapDomain => _classMapDomain; + /// /// Tries to register a serializer for a type. /// diff --git a/src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs b/src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs new file mode 100644 index 00000000000..658ddd6b74b --- /dev/null +++ b/src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs @@ -0,0 +1,383 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace MongoDB.Bson.Serialization +{ + /// + /// //TODO + /// + public interface IBsonClassMapDomain + { + /// + /// Gets the type of a member. + /// + /// The member info. + /// The type of the member. + Type GetMemberInfoType(MemberInfo memberInfo); + + /// + /// Gets all registered class maps. + /// + /// All registered class maps. + IEnumerable GetRegisteredClassMaps(); + + /// + /// Checks whether a class map is registered for a type. + /// + /// The type to check. + /// True if there is a class map registered for the type. + bool IsClassMapRegistered(Type type); + + /// + /// Looks up a class map (will AutoMap the class if no class map is registered). + /// + /// The class type. + /// The class map. + BsonClassMap LookupClassMap(Type classType); + + /// + /// Creates and registers a class map. + /// + /// The class. + /// The class map. + BsonClassMap RegisterClassMap(); + + /// + /// Creates and registers a class map. + /// + /// The class. + /// The class map initializer. + /// The class map. + BsonClassMap RegisterClassMap(Action> classMapInitializer); + + /// + /// Registers a class map. + /// + /// The class map. + void RegisterClassMap(BsonClassMap classMap); + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// True if this call registered the class map, false if the class map was already registered. + bool TryRegisterClassMap(); + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map. + /// True if this call registered the class map, false if the class map was already registered. + bool TryRegisterClassMap(BsonClassMap classMap); + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map initializer (only called if the class map is not already registered). + /// True if this call registered the class map, false if the class map was already registered. + bool TryRegisterClassMap(Action> classMapInitializer); + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map factory (only called if the class map is not already registered). + /// True if this call registered the class map, false if the class map was already registered. + bool TryRegisterClassMap(Func> classMapFactory); + } + + internal class BsonClassMapDomain : IBsonClassMapDomain + { + // private fields + private readonly Dictionary _classMaps = new(); + + /// + /// Gets the type of a member. + /// + /// The member info. + /// The type of the member. + public Type GetMemberInfoType(MemberInfo memberInfo) + { + if (memberInfo == null) + { + throw new ArgumentNullException("memberInfo"); + } + + if (memberInfo is FieldInfo) + { + return ((FieldInfo)memberInfo).FieldType; + } + else if (memberInfo is PropertyInfo) + { + return ((PropertyInfo)memberInfo).PropertyType; + } + + throw new NotSupportedException("Only field and properties are supported at this time."); + } + + /// + /// Gets all registered class maps. + /// + /// All registered class maps. + public IEnumerable GetRegisteredClassMaps() + { + BsonSerializer.ConfigLock.EnterReadLock(); //TODO It would make sense to look at this after the PR by Robert is merged + try + { + return _classMaps.Values.ToList(); // return a copy for thread safety + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + } + + /// + /// Checks whether a class map is registered for a type. + /// + /// The type to check. + /// True if there is a class map registered for the type. + public bool IsClassMapRegistered(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + BsonSerializer.ConfigLock.EnterReadLock(); + try + { + return _classMaps.ContainsKey(type); + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + } + + /// + /// Looks up a class map (will AutoMap the class if no class map is registered). + /// + /// The class type. + /// The class map. + public BsonClassMap LookupClassMap(Type classType) + { + if (classType == null) + { + throw new ArgumentNullException("classType"); + } + + BsonSerializer.ConfigLock.EnterReadLock(); + try + { + if (_classMaps.TryGetValue(classType, out var classMap)) + { + if (classMap.IsFrozen) + { + return classMap; + } + } + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + + // automatically create a new classMap for classType and register it (unless another thread does first) + // do the work of speculatively creating a new class map outside of holding any lock + var classMapDefinition = typeof(BsonClassMap<>); + var classMapType = classMapDefinition.MakeGenericType(classType); + var newClassMap = (BsonClassMap)Activator.CreateInstance(classMapType); + newClassMap.AutoMap(); + + BsonSerializer.ConfigLock.EnterWriteLock(); + try + { + if (!_classMaps.TryGetValue(classType, out var classMap)) + { + RegisterClassMap(newClassMap); + classMap = newClassMap; + } + + return classMap.Freeze(); + } + finally + { + BsonSerializer.ConfigLock.ExitWriteLock(); + } + } + + /// + /// Creates and registers a class map. + /// + /// The class. + /// The class map. + public BsonClassMap RegisterClassMap() + { + return RegisterClassMap(cm => { cm.AutoMap(); }); + } + + /// + /// Creates and registers a class map. + /// + /// The class. + /// The class map initializer. + /// The class map. + public BsonClassMap RegisterClassMap(Action> classMapInitializer) + { + var classMap = new BsonClassMap(classMapInitializer); + RegisterClassMap(classMap); + return classMap; + } + + /// + /// Registers a class map. + /// + /// The class map. + public void RegisterClassMap(BsonClassMap classMap) + { + if (classMap == null) + { + throw new ArgumentNullException("classMap"); + } + + BsonSerializer.ConfigLock.EnterWriteLock(); + try + { + // note: class maps can NOT be replaced (because derived classes refer to existing instance) + _classMaps.Add(classMap.ClassType, classMap); + BsonSerializer.RegisterDiscriminator(classMap.ClassType, classMap.Discriminator); + } + finally + { + BsonSerializer.ConfigLock.ExitWriteLock(); + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap() + { + return TryRegisterClassMap(ClassMapFactory); + + static BsonClassMap ClassMapFactory() + { + var classMap = new BsonClassMap(); + classMap.AutoMap(); + return classMap; + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map. + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap(BsonClassMap classMap) + { + if (classMap == null) + { + throw new ArgumentNullException(nameof(classMap)); + } + + return TryRegisterClassMap(ClassMapFactory); + + BsonClassMap ClassMapFactory() + { + return classMap; + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map initializer (only called if the class map is not already registered). + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap(Action> classMapInitializer) + { + if (classMapInitializer == null) + { + throw new ArgumentNullException(nameof(classMapInitializer)); + } + + return TryRegisterClassMap(ClassMapFactory); + + BsonClassMap ClassMapFactory() + { + return new BsonClassMap(classMapInitializer); + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map factory (only called if the class map is not already registered). + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap(Func> classMapFactory) + { + if (classMapFactory == null) + { + throw new ArgumentNullException(nameof(classMapFactory)); + } + + BsonSerializer.ConfigLock.EnterReadLock(); + try + { + if (_classMaps.ContainsKey(typeof(TClass))) + { + return false; + } + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + + BsonSerializer.ConfigLock.EnterWriteLock(); + try + { + if (_classMaps.ContainsKey(typeof(TClass))) + { + return false; + } + else + { + // create a classMap for TClass and register it + var classMap = classMapFactory(); + RegisterClassMap(classMap); + return true; + } + } + finally + { + BsonSerializer.ConfigLock.ExitWriteLock(); + } + } + } + +} \ No newline at end of file diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index d927c5a39cb..8f6791cd2f6 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -285,7 +285,14 @@ void Serialize( BsonSerializationArgs args = default(BsonSerializationArgs)); - //TODO These 3 methods were part of the internal interface before + /// + /// //TODO + /// + IBsonClassMapDomain ClassMapDomain { get; } + } + + internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain + { /// /// //TODO @@ -308,10 +315,7 @@ IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, /// /// bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type); - } - internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain - { ReaderWriterLockSlim ConfigLock { get; } } } \ No newline at end of file From 57425413cd562e7c4550424305a445f7fb13244b Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 4 Feb 2025 12:48:54 +0100 Subject: [PATCH 37/49] Fixed class --- .../Conventions/StandardDiscriminatorConvention.cs | 4 ++-- src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs index 16815ada484..071d624c7a5 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs @@ -105,10 +105,10 @@ public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSeriali if (bsonType == BsonType.Document) { // ensure KnownTypes of nominalType are registered (so IsTypeDiscriminated returns correct answer) - domain.EnsureKnownTypesAreRegistered(nominalType); //TODO ?? + (domain as IBsonSerializationDomainInternal)!.EnsureKnownTypesAreRegistered(nominalType); //TODO Should we move Ensure... to the public interface? // we can skip looking for a discriminator if nominalType has no discriminated sub types - if (domain.IsTypeDiscriminated(nominalType)) //TODO ?? + if (domain.IsTypeDiscriminated(nominalType)) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index 8f6791cd2f6..1a90a3281c7 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -293,7 +293,6 @@ void Serialize( internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain { - /// /// //TODO /// From d6d9ddce8a093bec7563bb871cec1aa653e4ff27 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 4 Feb 2025 12:56:33 +0100 Subject: [PATCH 38/49] Various corrections --- .../Serialization/BsonClassMap.cs | 38 +++++++++---------- .../BsonClassMapSerializationProvider.cs | 2 +- .../Serialization/BsonSerializationDomain.cs | 2 +- .../HierarchicalDiscriminatorConvention.cs | 2 +- .../ScalarDiscriminatorConvention.cs | 2 +- .../Serialization/IBsonSerializationDomain.cs | 2 +- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index ea6dcaa0771..10461ee646c 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -278,7 +278,7 @@ public static Type GetMemberInfoType(MemberInfo memberInfo) /// /// All registered class maps. public static IEnumerable GetRegisteredClassMaps() => - BsonSerializer.DefaultDomain.ClassMapDomain.GetRegisteredClassMaps(); + BsonSerializer.DefaultDomain.BsonClassMap.GetRegisteredClassMaps(); //TODO Used only in tests /// /// Checks whether a class map is registered for a type. @@ -286,7 +286,7 @@ public static IEnumerable GetRegisteredClassMaps() => /// The type to check. /// True if there is a class map registered for the type. public static bool IsClassMapRegistered(Type type) => - BsonSerializer.DefaultDomain.ClassMapDomain.IsClassMapRegistered(type); + BsonSerializer.DefaultDomain.BsonClassMap.IsClassMapRegistered(type); //TODO Used only in tests /// /// Looks up a class map (will AutoMap the class if no class map is registered). @@ -294,15 +294,15 @@ public static bool IsClassMapRegistered(Type type) => /// The class type. /// The class map. public static BsonClassMap LookupClassMap(Type classType) => - BsonSerializer.DefaultDomain.ClassMapDomain.LookupClassMap(classType); + BsonSerializer.DefaultDomain.BsonClassMap.LookupClassMap(classType); /// /// Creates and registers a class map. /// /// The class. /// The class map. - public static BsonClassMap RegisterClassMap()=> - BsonSerializer.DefaultDomain.ClassMapDomain.RegisterClassMap(); + public static BsonClassMap RegisterClassMap()=> //TODO Used only in tests + BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(); /// /// Creates and registers a class map. @@ -310,23 +310,23 @@ public static BsonClassMap RegisterClassMap()=> /// The class. /// The class map initializer. /// The class map. - public static BsonClassMap RegisterClassMap(Action> classMapInitializer) - => BsonSerializer.DefaultDomain.ClassMapDomain.RegisterClassMap(classMapInitializer); + public static BsonClassMap RegisterClassMap(Action> classMapInitializer) //TODO Used only in tests + => BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(classMapInitializer); /// /// Registers a class map. /// /// The class map. - public static void RegisterClassMap(BsonClassMap classMap) - => BsonSerializer.DefaultDomain.ClassMapDomain.RegisterClassMap(classMap); + public static void RegisterClassMap(BsonClassMap classMap) //TODO Used only in tests + => BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(classMap); /// /// Registers a class map if it is not already registered. /// /// The class. /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap() - => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(); + public static bool TryRegisterClassMap() //TODO Used only in tests + => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(); /// /// Registers a class map if it is not already registered. @@ -334,8 +334,8 @@ public static bool TryRegisterClassMap() /// The class. /// The class map. /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap(BsonClassMap classMap) - => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(classMap); + public static bool TryRegisterClassMap(BsonClassMap classMap) //TODO Used only in tests + => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMap); /// /// Registers a class map if it is not already registered. @@ -343,8 +343,8 @@ public static bool TryRegisterClassMap(BsonClassMap classMap) /// The class. /// The class map initializer (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap(Action> classMapInitializer) - => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(classMapInitializer); + public static bool TryRegisterClassMap(Action> classMapInitializer) //TODO Used only in tests + => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMapInitializer); /// /// Registers a class map if it is not already registered. @@ -352,8 +352,8 @@ public static bool TryRegisterClassMap(Action> clas /// The class. /// The class map factory (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap(Func> classMapFactory) - => BsonSerializer.DefaultDomain.ClassMapDomain.TryRegisterClassMap(classMapFactory); + public static bool TryRegisterClassMap(Func> classMapFactory) //TODO Used only in tests + => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMapFactory); // public methods /// @@ -454,7 +454,7 @@ private BsonClassMap Freeze(FreezeContext context) { if (_baseClassMap == null) { - _baseClassMap = LookupClassMap(baseType); + _baseClassMap = context.SerializationDomain.BsonClassMap.LookupClassMap(baseType); } _baseClassMap.Freeze(context); //TODO This is not necessary, because LookupClassMap will only return a frozen class map _discriminatorIsRequired |= _baseClassMap._discriminatorIsRequired; @@ -557,7 +557,7 @@ private BsonClassMap Freeze(FreezeContext context) while (context.KnownTypesQueue.Count != 0) { var knownType = context.KnownTypesQueue.Dequeue(); - LookupClassMap(knownType); // will AutoMap and/or Freeze knownType if necessary + context.SerializationDomain.BsonClassMap.LookupClassMap(knownType); // will AutoMap and/or Freeze knownType if necessary } } } diff --git a/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs b/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs index ac088360c2d..824d665e905 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs @@ -41,7 +41,7 @@ public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry !typeof(Array).GetTypeInfo().IsAssignableFrom(type) && !typeof(Enum).GetTypeInfo().IsAssignableFrom(type)) { - var classMap = BsonClassMap.LookupClassMap(type); + var classMap = BsonClassMap.LookupClassMap(type); //TODO We need to find a way to pass the domain here var classMapSerializerDefinition = typeof(BsonClassMapSerializer<>); var classMapSerializerType = classMapSerializerDefinition.MakeGenericType(type); return (IBsonSerializer)Activator.CreateInstance(classMapSerializerType, classMap); diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index ccf91bc7647..ae52e788b4d 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -732,7 +732,7 @@ public void Serialize( serializer.Serialize(context, args, value); } - public IBsonClassMapDomain ClassMapDomain => _classMapDomain; + public IBsonClassMapDomain BsonClassMap => _classMapDomain; /// /// Tries to register a serializer for a type. diff --git a/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs index aa249b62c62..9b3cd73866e 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs @@ -48,7 +48,7 @@ public override BsonValue GetDiscriminator(Type nominalType, Type actualType) => public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) { // TODO: this isn't quite right, not all classes are serialized using a class map serializer - var classMap = BsonClassMap.LookupClassMap(actualType); + var classMap = domain.BsonClassMap.LookupClassMap(actualType); if (actualType != nominalType || classMap.DiscriminatorIsRequired || classMap.HasRootClass) { if (classMap.HasRootClass && !classMap.IsRootClass) diff --git a/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs index dbb4d00871a..6045ac80a1b 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs @@ -46,7 +46,7 @@ public override BsonValue GetDiscriminator(Type nominalType, Type actualType) => public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) { // TODO: this isn't quite right, not all classes are serialized using a class map serializer - var classMap = BsonClassMap.LookupClassMap(actualType); + var classMap = domain.BsonClassMap.LookupClassMap(actualType); if (actualType != nominalType || classMap.DiscriminatorIsRequired) { return classMap.Discriminator; diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index 1a90a3281c7..fe97dbe6063 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -288,7 +288,7 @@ void Serialize( /// /// //TODO /// - IBsonClassMapDomain ClassMapDomain { get; } + IBsonClassMapDomain BsonClassMap { get; } } internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain From 3b27b43d7963b92f4b3a6f738e314b9879ba999d Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 4 Feb 2025 12:59:25 +0100 Subject: [PATCH 39/49] Moved class map to another file --- .../Serialization/BsonClassMapDomain.cs | 257 ++++++++++++++++ .../Serialization/IBsonClassMapDomain.cs | 284 ------------------ 2 files changed, 257 insertions(+), 284 deletions(-) create mode 100644 src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs diff --git a/src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs b/src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs new file mode 100644 index 00000000000..3651bf782a6 --- /dev/null +++ b/src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace MongoDB.Bson.Serialization; + +internal class BsonClassMapDomain : IBsonClassMapDomain +{ + // private fields + private readonly Dictionary _classMaps = new(); + + /// + /// Gets all registered class maps. + /// + /// All registered class maps. + public IEnumerable GetRegisteredClassMaps() + { + BsonSerializer.ConfigLock.EnterReadLock(); //TODO It would make sense to look at this after the PR by Robert is merged + try + { + return _classMaps.Values.ToList(); // return a copy for thread safety + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + } + + /// + /// Checks whether a class map is registered for a type. + /// + /// The type to check. + /// True if there is a class map registered for the type. + public bool IsClassMapRegistered(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + BsonSerializer.ConfigLock.EnterReadLock(); + try + { + return _classMaps.ContainsKey(type); + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + } + + /// + /// Looks up a class map (will AutoMap the class if no class map is registered). + /// + /// The class type. + /// The class map. + public BsonClassMap LookupClassMap(Type classType) + { + if (classType == null) + { + throw new ArgumentNullException("classType"); + } + + BsonSerializer.ConfigLock.EnterReadLock(); + try + { + if (_classMaps.TryGetValue(classType, out var classMap)) + { + if (classMap.IsFrozen) + { + return classMap; + } + } + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + + // automatically create a new classMap for classType and register it (unless another thread does first) + // do the work of speculatively creating a new class map outside of holding any lock + var classMapDefinition = typeof(BsonClassMap<>); + var classMapType = classMapDefinition.MakeGenericType(classType); + var newClassMap = (BsonClassMap)Activator.CreateInstance(classMapType); + newClassMap.AutoMap(); + + BsonSerializer.ConfigLock.EnterWriteLock(); + try + { + if (!_classMaps.TryGetValue(classType, out var classMap)) + { + RegisterClassMap(newClassMap); + classMap = newClassMap; + } + + return classMap.Freeze(); + } + finally + { + BsonSerializer.ConfigLock.ExitWriteLock(); + } + } + + /// + /// Creates and registers a class map. + /// + /// The class. + /// The class map. + public BsonClassMap RegisterClassMap() + { + return RegisterClassMap(cm => { cm.AutoMap(); }); + } + + /// + /// Creates and registers a class map. + /// + /// The class. + /// The class map initializer. + /// The class map. + public BsonClassMap RegisterClassMap(Action> classMapInitializer) + { + var classMap = new BsonClassMap(classMapInitializer); + RegisterClassMap(classMap); + return classMap; + } + + /// + /// Registers a class map. + /// + /// The class map. + public void RegisterClassMap(BsonClassMap classMap) + { + if (classMap == null) + { + throw new ArgumentNullException("classMap"); + } + + BsonSerializer.ConfigLock.EnterWriteLock(); + try + { + // note: class maps can NOT be replaced (because derived classes refer to existing instance) + _classMaps.Add(classMap.ClassType, classMap); + BsonSerializer.RegisterDiscriminator(classMap.ClassType, classMap.Discriminator); + } + finally + { + BsonSerializer.ConfigLock.ExitWriteLock(); + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap() + { + return TryRegisterClassMap(ClassMapFactory); + + static BsonClassMap ClassMapFactory() + { + var classMap = new BsonClassMap(); + classMap.AutoMap(); + return classMap; + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map. + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap(BsonClassMap classMap) + { + if (classMap == null) + { + throw new ArgumentNullException(nameof(classMap)); + } + + return TryRegisterClassMap(ClassMapFactory); + + BsonClassMap ClassMapFactory() + { + return classMap; + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map initializer (only called if the class map is not already registered). + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap(Action> classMapInitializer) + { + if (classMapInitializer == null) + { + throw new ArgumentNullException(nameof(classMapInitializer)); + } + + return TryRegisterClassMap(ClassMapFactory); + + BsonClassMap ClassMapFactory() + { + return new BsonClassMap(classMapInitializer); + } + } + + /// + /// Registers a class map if it is not already registered. + /// + /// The class. + /// The class map factory (only called if the class map is not already registered). + /// True if this call registered the class map, false if the class map was already registered. + public bool TryRegisterClassMap(Func> classMapFactory) + { + if (classMapFactory == null) + { + throw new ArgumentNullException(nameof(classMapFactory)); + } + + BsonSerializer.ConfigLock.EnterReadLock(); + try + { + if (_classMaps.ContainsKey(typeof(TClass))) + { + return false; + } + } + finally + { + BsonSerializer.ConfigLock.ExitReadLock(); + } + + BsonSerializer.ConfigLock.EnterWriteLock(); + try + { + if (_classMaps.ContainsKey(typeof(TClass))) + { + return false; + } + else + { + // create a classMap for TClass and register it + var classMap = classMapFactory(); + RegisterClassMap(classMap); + return true; + } + } + finally + { + BsonSerializer.ConfigLock.ExitWriteLock(); + } + } +} \ No newline at end of file diff --git a/src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs b/src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs index 658ddd6b74b..0c569076ccb 100644 --- a/src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonClassMapDomain.cs @@ -15,7 +15,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; namespace MongoDB.Bson.Serialization @@ -25,13 +24,6 @@ namespace MongoDB.Bson.Serialization /// public interface IBsonClassMapDomain { - /// - /// Gets the type of a member. - /// - /// The member info. - /// The type of the member. - Type GetMemberInfoType(MemberInfo memberInfo); - /// /// Gets all registered class maps. /// @@ -104,280 +96,4 @@ public interface IBsonClassMapDomain /// True if this call registered the class map, false if the class map was already registered. bool TryRegisterClassMap(Func> classMapFactory); } - - internal class BsonClassMapDomain : IBsonClassMapDomain - { - // private fields - private readonly Dictionary _classMaps = new(); - - /// - /// Gets the type of a member. - /// - /// The member info. - /// The type of the member. - public Type GetMemberInfoType(MemberInfo memberInfo) - { - if (memberInfo == null) - { - throw new ArgumentNullException("memberInfo"); - } - - if (memberInfo is FieldInfo) - { - return ((FieldInfo)memberInfo).FieldType; - } - else if (memberInfo is PropertyInfo) - { - return ((PropertyInfo)memberInfo).PropertyType; - } - - throw new NotSupportedException("Only field and properties are supported at this time."); - } - - /// - /// Gets all registered class maps. - /// - /// All registered class maps. - public IEnumerable GetRegisteredClassMaps() - { - BsonSerializer.ConfigLock.EnterReadLock(); //TODO It would make sense to look at this after the PR by Robert is merged - try - { - return _classMaps.Values.ToList(); // return a copy for thread safety - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - } - - /// - /// Checks whether a class map is registered for a type. - /// - /// The type to check. - /// True if there is a class map registered for the type. - public bool IsClassMapRegistered(Type type) - { - if (type == null) - { - throw new ArgumentNullException("type"); - } - - BsonSerializer.ConfigLock.EnterReadLock(); - try - { - return _classMaps.ContainsKey(type); - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - } - - /// - /// Looks up a class map (will AutoMap the class if no class map is registered). - /// - /// The class type. - /// The class map. - public BsonClassMap LookupClassMap(Type classType) - { - if (classType == null) - { - throw new ArgumentNullException("classType"); - } - - BsonSerializer.ConfigLock.EnterReadLock(); - try - { - if (_classMaps.TryGetValue(classType, out var classMap)) - { - if (classMap.IsFrozen) - { - return classMap; - } - } - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - - // automatically create a new classMap for classType and register it (unless another thread does first) - // do the work of speculatively creating a new class map outside of holding any lock - var classMapDefinition = typeof(BsonClassMap<>); - var classMapType = classMapDefinition.MakeGenericType(classType); - var newClassMap = (BsonClassMap)Activator.CreateInstance(classMapType); - newClassMap.AutoMap(); - - BsonSerializer.ConfigLock.EnterWriteLock(); - try - { - if (!_classMaps.TryGetValue(classType, out var classMap)) - { - RegisterClassMap(newClassMap); - classMap = newClassMap; - } - - return classMap.Freeze(); - } - finally - { - BsonSerializer.ConfigLock.ExitWriteLock(); - } - } - - /// - /// Creates and registers a class map. - /// - /// The class. - /// The class map. - public BsonClassMap RegisterClassMap() - { - return RegisterClassMap(cm => { cm.AutoMap(); }); - } - - /// - /// Creates and registers a class map. - /// - /// The class. - /// The class map initializer. - /// The class map. - public BsonClassMap RegisterClassMap(Action> classMapInitializer) - { - var classMap = new BsonClassMap(classMapInitializer); - RegisterClassMap(classMap); - return classMap; - } - - /// - /// Registers a class map. - /// - /// The class map. - public void RegisterClassMap(BsonClassMap classMap) - { - if (classMap == null) - { - throw new ArgumentNullException("classMap"); - } - - BsonSerializer.ConfigLock.EnterWriteLock(); - try - { - // note: class maps can NOT be replaced (because derived classes refer to existing instance) - _classMaps.Add(classMap.ClassType, classMap); - BsonSerializer.RegisterDiscriminator(classMap.ClassType, classMap.Discriminator); - } - finally - { - BsonSerializer.ConfigLock.ExitWriteLock(); - } - } - - /// - /// Registers a class map if it is not already registered. - /// - /// The class. - /// True if this call registered the class map, false if the class map was already registered. - public bool TryRegisterClassMap() - { - return TryRegisterClassMap(ClassMapFactory); - - static BsonClassMap ClassMapFactory() - { - var classMap = new BsonClassMap(); - classMap.AutoMap(); - return classMap; - } - } - - /// - /// Registers a class map if it is not already registered. - /// - /// The class. - /// The class map. - /// True if this call registered the class map, false if the class map was already registered. - public bool TryRegisterClassMap(BsonClassMap classMap) - { - if (classMap == null) - { - throw new ArgumentNullException(nameof(classMap)); - } - - return TryRegisterClassMap(ClassMapFactory); - - BsonClassMap ClassMapFactory() - { - return classMap; - } - } - - /// - /// Registers a class map if it is not already registered. - /// - /// The class. - /// The class map initializer (only called if the class map is not already registered). - /// True if this call registered the class map, false if the class map was already registered. - public bool TryRegisterClassMap(Action> classMapInitializer) - { - if (classMapInitializer == null) - { - throw new ArgumentNullException(nameof(classMapInitializer)); - } - - return TryRegisterClassMap(ClassMapFactory); - - BsonClassMap ClassMapFactory() - { - return new BsonClassMap(classMapInitializer); - } - } - - /// - /// Registers a class map if it is not already registered. - /// - /// The class. - /// The class map factory (only called if the class map is not already registered). - /// True if this call registered the class map, false if the class map was already registered. - public bool TryRegisterClassMap(Func> classMapFactory) - { - if (classMapFactory == null) - { - throw new ArgumentNullException(nameof(classMapFactory)); - } - - BsonSerializer.ConfigLock.EnterReadLock(); - try - { - if (_classMaps.ContainsKey(typeof(TClass))) - { - return false; - } - } - finally - { - BsonSerializer.ConfigLock.ExitReadLock(); - } - - BsonSerializer.ConfigLock.EnterWriteLock(); - try - { - if (_classMaps.ContainsKey(typeof(TClass))) - { - return false; - } - else - { - // create a classMap for TClass and register it - var classMap = classMapFactory(); - RegisterClassMap(classMap); - return true; - } - } - finally - { - BsonSerializer.ConfigLock.ExitWriteLock(); - } - } - } - } \ No newline at end of file From 98682bb683c065dade4e30a3779d62d812e33dcd Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 4 Feb 2025 13:00:56 +0100 Subject: [PATCH 40/49] Removed comments --- src/MongoDB.Bson/Serialization/BsonClassMap.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 10461ee646c..e3dec887957 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -278,7 +278,7 @@ public static Type GetMemberInfoType(MemberInfo memberInfo) /// /// All registered class maps. public static IEnumerable GetRegisteredClassMaps() => - BsonSerializer.DefaultDomain.BsonClassMap.GetRegisteredClassMaps(); //TODO Used only in tests + BsonSerializer.DefaultDomain.BsonClassMap.GetRegisteredClassMaps(); /// /// Checks whether a class map is registered for a type. @@ -286,7 +286,7 @@ public static IEnumerable GetRegisteredClassMaps() => /// The type to check. /// True if there is a class map registered for the type. public static bool IsClassMapRegistered(Type type) => - BsonSerializer.DefaultDomain.BsonClassMap.IsClassMapRegistered(type); //TODO Used only in tests + BsonSerializer.DefaultDomain.BsonClassMap.IsClassMapRegistered(type); /// /// Looks up a class map (will AutoMap the class if no class map is registered). @@ -301,7 +301,7 @@ public static BsonClassMap LookupClassMap(Type classType) => /// /// The class. /// The class map. - public static BsonClassMap RegisterClassMap()=> //TODO Used only in tests + public static BsonClassMap RegisterClassMap()=> BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(); /// @@ -310,14 +310,14 @@ public static BsonClassMap RegisterClassMap()=> //TODO Used onl /// The class. /// The class map initializer. /// The class map. - public static BsonClassMap RegisterClassMap(Action> classMapInitializer) //TODO Used only in tests + public static BsonClassMap RegisterClassMap(Action> classMapInitializer) => BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(classMapInitializer); /// /// Registers a class map. /// /// The class map. - public static void RegisterClassMap(BsonClassMap classMap) //TODO Used only in tests + public static void RegisterClassMap(BsonClassMap classMap) => BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(classMap); /// @@ -325,7 +325,7 @@ public static void RegisterClassMap(BsonClassMap classMap) //TODO Used only in /// /// The class. /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap() //TODO Used only in tests + public static bool TryRegisterClassMap() => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(); /// @@ -334,7 +334,7 @@ public static bool TryRegisterClassMap() //TODO Used only in tests /// The class. /// The class map. /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap(BsonClassMap classMap) //TODO Used only in tests + public static bool TryRegisterClassMap(BsonClassMap classMap) => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMap); /// @@ -343,7 +343,7 @@ public static bool TryRegisterClassMap(BsonClassMap classMap) / /// The class. /// The class map initializer (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap(Action> classMapInitializer) //TODO Used only in tests + public static bool TryRegisterClassMap(Action> classMapInitializer) => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMapInitializer); /// @@ -352,7 +352,7 @@ public static bool TryRegisterClassMap(Action> clas /// The class. /// The class map factory (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. - public static bool TryRegisterClassMap(Func> classMapFactory) //TODO Used only in tests + public static bool TryRegisterClassMap(Func> classMapFactory) => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMapFactory); // public methods From dc3311250f514092a70341ef42a6b595e96afec5 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 4 Feb 2025 13:15:37 +0100 Subject: [PATCH 41/49] Passing domain in serializer registry --- .../BsonClassMapSerializationProvider.cs | 2 +- .../Serialization/BsonSerializationDomain.cs | 2 +- .../Serialization/BsonSerializerRegistry.cs | 18 ++++++++- .../Serialization/IBsonSerializerRegistry.cs | 5 +++ src/MongoDB.Driver/MongoCollectionSettings.cs | 2 +- .../MultipleRegistriesTests.cs | 39 ++++++++++--------- 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs b/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs index 824d665e905..16ee04bb8ba 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMapSerializationProvider.cs @@ -41,7 +41,7 @@ public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry !typeof(Array).GetTypeInfo().IsAssignableFrom(type) && !typeof(Enum).GetTypeInfo().IsAssignableFrom(type)) { - var classMap = BsonClassMap.LookupClassMap(type); //TODO We need to find a way to pass the domain here + var classMap = serializerRegistry.SerializationDomain.BsonClassMap.LookupClassMap(type); var classMapSerializerDefinition = typeof(BsonClassMapSerializer<>); var classMapSerializerType = classMapSerializerDefinition.MakeGenericType(type); return (IBsonSerializer)Activator.CreateInstance(classMapSerializerType, classMap); diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index ae52e788b4d..5b4d544886e 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -798,7 +798,7 @@ public void Dispose() // private methods private void CreateSerializerRegistry() { - _serializerRegistry = new BsonSerializerRegistry(); + _serializerRegistry = new BsonSerializerRegistry(this); _typeMappingSerializationProvider = new TypeMappingSerializationProvider(); // order matters. It's in reverse order of how they'll get consumed diff --git a/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs b/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs index 429386f6019..dfdc8ddf8fa 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs @@ -28,19 +28,35 @@ public sealed class BsonSerializerRegistry : IBsonSerializerRegistry private readonly ConcurrentDictionary _cache; private readonly ConcurrentStack _serializationProviders; private readonly Func _createSerializer; + private readonly IBsonSerializationDomain _serializationDomain; // constructors /// /// Initializes a new instance of the class. /// - public BsonSerializerRegistry() + public BsonSerializerRegistry(): + this(BsonSerializer.DefaultDomain) + { + } + + /// + /// //TODO + /// + /// + public BsonSerializerRegistry(IBsonSerializationDomain serializationDomain) { _cache = new ConcurrentDictionary(); _serializationProviders = new ConcurrentStack(); _createSerializer = CreateSerializer; + _serializationDomain = serializationDomain; } // public methods + /// + /// //TODO + /// + public IBsonSerializationDomain SerializationDomain => _serializationDomain; + /// /// Gets the serializer for the specified . /// If none is already registered, the serialization providers will be used to create a serializer and it will be automatically registered. diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializerRegistry.cs b/src/MongoDB.Bson/Serialization/IBsonSerializerRegistry.cs index 9a9d5f6b8f9..f23ce17703e 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializerRegistry.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializerRegistry.cs @@ -22,6 +22,11 @@ namespace MongoDB.Bson.Serialization /// public interface IBsonSerializerRegistry { + /// + /// //TODO + /// + public IBsonSerializationDomain SerializationDomain { get; } + /// /// Gets the serializer for the specified . /// diff --git a/src/MongoDB.Driver/MongoCollectionSettings.cs b/src/MongoDB.Driver/MongoCollectionSettings.cs index 44ecb254646..83fc3de4c9e 100644 --- a/src/MongoDB.Driver/MongoCollectionSettings.cs +++ b/src/MongoDB.Driver/MongoCollectionSettings.cs @@ -117,7 +117,7 @@ public ReadPreference ReadPreference /// /// Gets the serializer registry. /// - public IBsonSerializerRegistry SerializerRegistry => SerializationDomain.SerializerRegistry; + public IBsonSerializerRegistry SerializerRegistry => SerializationDomain.SerializerRegistry; //TODO We should try passing down the domain instead of the registry... /// /// //TODO diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs index ee0aec1b593..5e52613ca68 100644 --- a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -27,25 +27,26 @@ public class MultipleRegistriesTests [Fact] public void TestSerialization() { - // At the moment having this uncommented would make the test fail due to the static caching of class maps - // { - // var client = DriverTestConfiguration.CreateMongoClient(); - // var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); - // db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); - // var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); - // var bsonCollection = - // db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); - // - // var person = new Person { Id = ObjectId.Parse("6797b56bf5495bf53aa3078f"), Name = "Mario", Age = 24 }; - // collection.InsertOne(person); - // - // var retrieved = bsonCollection.FindSync("{}").ToList().Single(); - // var toString = retrieved.ToString(); - // - // var expectedVal = - // """{ "_id" : { "$oid" : "6797b56bf5495bf53aa3078f" }, "Name" : "Mario", "Age" : 24 }"""; - // Assert.Equal(expectedVal, toString); - // } + { + var client = DriverTestConfiguration.CreateMongoClient(); + var db = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName); + db.DropCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + var collection = db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + var bsonCollection = + db.GetCollection(DriverTestConfiguration.CollectionNamespace.CollectionName); + + var person = new Person { Id = ObjectId.Parse("6797b56bf5495bf53aa3078f"), Name = "Mario", Age = 24 }; + collection.InsertOne(person); + + var retrieved = bsonCollection.FindSync("{}").ToList().Single(); + var toString = retrieved.ToString(); + + var expectedVal = + """{ "_id" : { "$oid" : "6797b56bf5495bf53aa3078f" }, "Name" : "Mario", "Age" : 24 }"""; + Assert.Equal(expectedVal, toString); + } + + //The first section demonstrates that the class maps are also separated { var customDomain = BsonSerializer.CreateDomain(); From a45b02798c2af6d6c6f03a0f27f2213c5f88c7de Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 5 Feb 2025 11:09:19 +0100 Subject: [PATCH 42/49] Small improvements --- src/MongoDB.Bson/Serialization/BsonClassMap.cs | 7 +++---- .../Serializers/DiscriminatedInterfaceSerializer.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index e3dec887957..19cc247562e 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -418,16 +418,15 @@ internal class FreezeContext /// The frozen class map. public BsonClassMap Freeze() => Freeze(BsonSerializer.DefaultDomain); - internal BsonClassMap Freeze(IBsonSerializationDomain domain) { - var freezeContext = new FreezeContext() { SerializationDomain = domain }; + var freezeContext = new FreezeContext { SerializationDomain = domain }; return Freeze(freezeContext); } - private BsonClassMap Freeze(FreezeContext context) + private BsonClassMap Freeze(FreezeContext context) //TODO This is not completely correct, because LookupClassMap calls freeze { - var configLock = (context.SerializationDomain as IBsonSerializationDomainInternal)!.ConfigLock; + var configLock = (context.SerializationDomain as IBsonSerializationDomainInternal)!.ConfigLock; //TODO This is ugly configLock.EnterReadLock(); try { diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs index 75afa999605..ea38dd969f9 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs @@ -48,7 +48,7 @@ private static IBsonSerializer CreateInterfaceSerializer(IBsonSerial var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); classMap.AutoMap(); classMap.SetDiscriminatorConvention(domain.LookupDiscriminatorConvention(typeof(TInterface))); - classMap.Freeze(); + classMap.Freeze(domain); return new BsonClassMapSerializer(classMap); } #endregion From 3f9c37c5f87f3710e4320e0533570d7c1c1e8348 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 5 Feb 2025 16:33:36 +0100 Subject: [PATCH 43/49] Small corrections --- src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs | 2 +- src/MongoDB.Bson/Serialization/BsonSerializationContext.cs | 2 +- src/MongoDB.Driver/MongoCollectionSettings.cs | 1 + src/MongoDB.Driver/MongoDatabaseSettings.cs | 1 + .../MongoDB.Bson.Tests/ObjectModel/BsonDocumentWrapperTests.cs | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index a33d5a62a1c..7cb2f337ed7 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -41,7 +41,7 @@ private BsonDeserializationContext( _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; - _domain = reader.Settings.SerializationDomain ?? BsonSerializer.DefaultDomain; + _domain = reader.Settings?.SerializationDomain ?? BsonSerializer.DefaultDomain; } // public properties diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs index eedef3fea48..21a2524f179 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs @@ -35,7 +35,7 @@ private BsonSerializationContext( { _writer = writer; _isDynamicType = isDynamicType; - _domain = writer.Settings.SerializationDomain ?? BsonSerializer.DefaultDomain; + _domain = writer.Settings?.SerializationDomain ?? BsonSerializer.DefaultDomain; } // public properties diff --git a/src/MongoDB.Driver/MongoCollectionSettings.cs b/src/MongoDB.Driver/MongoCollectionSettings.cs index 83fc3de4c9e..e5dbdf6dc43 100644 --- a/src/MongoDB.Driver/MongoCollectionSettings.cs +++ b/src/MongoDB.Driver/MongoCollectionSettings.cs @@ -180,6 +180,7 @@ public virtual MongoCollectionSettings Clone() clone._readPreference = _readPreference.Clone(); clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); + clone._serializationDomain = _serializationDomain; //TODO .clone...? return clone; } diff --git a/src/MongoDB.Driver/MongoDatabaseSettings.cs b/src/MongoDB.Driver/MongoDatabaseSettings.cs index 9ba9fe0f0db..2a098f6d05b 100644 --- a/src/MongoDB.Driver/MongoDatabaseSettings.cs +++ b/src/MongoDB.Driver/MongoDatabaseSettings.cs @@ -164,6 +164,7 @@ public MongoDatabaseSettings Clone() clone._readPreference = _readPreference.Clone(); clone._writeConcern = _writeConcern.Clone(); clone._writeEncoding = _writeEncoding.Clone(); + clone._serializationDomain = _serializationDomain; return clone; } diff --git a/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentWrapperTests.cs b/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentWrapperTests.cs index a1f94fb3b41..fb115e1df62 100644 --- a/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentWrapperTests.cs +++ b/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentWrapperTests.cs @@ -310,7 +310,7 @@ public void TestCreateWithNominalTypeAndObject() Assert.Same(c, wrapper.Wrapped); Assert.Equal(false, wrapper.IsMaterialized); - wrapper = BsonDocumentWrapper.Create(typeof(C), null); + wrapper = BsonDocumentWrapper.Create(typeof(C)); Assert.Same(BsonSerializer.LookupSerializer(typeof(C)), wrapper.Serializer); Assert.Same(null, wrapper.Wrapped); Assert.Equal(false, wrapper.IsMaterialized); From f0487d3009661fc42fed1eaf222763000cac15ba Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 10 Feb 2025 15:51:10 +0100 Subject: [PATCH 44/49] Renamin to serialization domain --- src/MongoDB.Bson/BsonExtensionMethods.cs | 6 +- .../ObjectModel/BsonDocumentWrapper.cs | 8 +- .../Serialization/BsonClassMap.cs | 22 ++--- .../BsonDeserializationContext.cs | 8 +- .../Serialization/BsonMemberMap.cs | 2 +- .../Serialization/BsonSerializationContext.cs | 6 +- .../Serialization/BsonSerializer.cs | 82 +++++++++---------- .../Serialization/BsonSerializerRegistry.cs | 2 +- .../Conventions/AttributeConventionPack.cs | 4 +- .../CamelCaseElementNameConvention.cs | 2 +- .../DelegateMemberMapConvention.cs | 2 +- .../DelegatePostProcessingConvention.cs | 2 +- .../EnumRepresentationConvention.cs | 2 +- .../HierarchicalDiscriminatorConvention.cs | 2 +- .../Conventions/IgnoreIfDefaultConvention.cs | 2 +- .../Conventions/IgnoreIfNullConvention.cs | 2 +- .../LookupIdGeneratorConvention.cs | 2 +- .../MemberDefaultValueConvention.cs | 2 +- .../MemberNameElementNameConvention.cs | 2 +- .../Conventions/NoIdMemberConvention.cs | 2 +- .../ObjectDiscriminatorConvention.cs | 2 +- .../ObjectSerializerAllowedTypesConvention.cs | 2 +- .../Conventions/ResetMemberMapsConvention.cs | 2 +- .../ScalarDiscriminatorConvention.cs | 2 +- .../StandardDiscriminatorConvention.cs | 2 +- .../StringIdStoredAsObjectIdConvention.cs | 2 +- .../StringObjectIdIdGeneratorConvention.cs | 2 +- .../Serializers/BsonClassMapSerializer.cs | 10 +-- .../Serializers/BsonDocumentSerializer.cs | 2 +- .../Serializers/BsonValueSerializerBase.cs | 2 +- .../Serializers/ClassSerializerBase.cs | 4 +- .../DiscriminatedInterfaceSerializer.cs | 4 +- .../DiscriminatedWrapperSerializer.cs | 2 +- .../DynamicDocumentBaseSerializer.cs | 4 +- .../Serializers/ExpandoObjectSerializer.cs | 2 +- ...mpliedImplementationInterfaceSerializer.cs | 2 +- .../Serializers/ObjectSerializer.cs | 4 +- .../UndiscriminatedActualTypeSerializer.cs | 2 +- src/MongoDB.Driver/MongoClientSettings.cs | 2 +- src/MongoDB.Driver/OfTypeSerializer.cs | 2 +- 40 files changed, 108 insertions(+), 110 deletions(-) diff --git a/src/MongoDB.Bson/BsonExtensionMethods.cs b/src/MongoDB.Bson/BsonExtensionMethods.cs index 99768d23510..b72880e22f8 100644 --- a/src/MongoDB.Bson/BsonExtensionMethods.cs +++ b/src/MongoDB.Bson/BsonExtensionMethods.cs @@ -69,7 +69,7 @@ public static byte[] ToBson( IBsonSerializer serializer = null, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs), - int estimatedBsonSize = 0) => ToBson(obj, nominalType, BsonSerializer.DefaultDomain, writerSettings, + int estimatedBsonSize = 0) => ToBson(obj, nominalType, BsonSerializer.DefaultSerializationDomain, writerSettings, serializer, configurator, args, estimatedBsonSize); /// @@ -164,7 +164,7 @@ public static BsonDocument ToBsonDocument( IBsonSerializer serializer = null, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)) => ToBsonDocument(obj, nominalType, - BsonSerializer.DefaultDomain, serializer, configurator, args); + BsonSerializer.DefaultSerializationDomain, serializer, configurator, args); /// /// //TODO @@ -273,7 +273,7 @@ public static string ToJson( IBsonSerializer serializer = null, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)) - => ToJson(obj, nominalType, BsonSerializer.DefaultDomain, writerSettings, serializer, configurator, args); + => ToJson(obj, nominalType, BsonSerializer.DefaultSerializationDomain, writerSettings, serializer, configurator, args); /// /// //TODO diff --git a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs index 5a6eb642fee..2640dbe5614 100644 --- a/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs +++ b/src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs @@ -92,7 +92,7 @@ public object Wrapped /// The wrapped object. /// A BsonDocumentWrapper. public static BsonDocumentWrapper Create(TNominalType value) => - Create(value, BsonSerializer.DefaultDomain); + Create(value, BsonSerializer.DefaultSerializationDomain); /// /// //TODO @@ -113,7 +113,7 @@ public static BsonDocumentWrapper Create(TNominalType value, IBson /// The wrapped object. /// A BsonDocumentWrapper. public static BsonDocumentWrapper Create(Type nominalType, object value) => - Create(nominalType, value, BsonSerializer.DefaultDomain); + Create(nominalType, value, BsonSerializer.DefaultSerializationDomain); /// /// //TODO @@ -135,7 +135,7 @@ public static BsonDocumentWrapper Create(Type nominalType, object value, IBsonSe /// A list of wrapped objects. /// A list of BsonDocumentWrappers. public static IEnumerable CreateMultiple(IEnumerable values) => - CreateMultiple(values, BsonSerializer.DefaultDomain); + CreateMultiple(values, BsonSerializer.DefaultSerializationDomain); /// /// //TODO @@ -163,7 +163,7 @@ public static IEnumerable CreateMultiple(IEnu /// A list of wrapped objects. /// A list of BsonDocumentWrappers. public static IEnumerable CreateMultiple(Type nominalType, IEnumerable values) => - CreateMultiple(nominalType, values, BsonSerializer.DefaultDomain); + CreateMultiple(nominalType, values, BsonSerializer.DefaultSerializationDomain); /// /// //TODO diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 19cc247562e..061e7702a39 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -278,7 +278,7 @@ public static Type GetMemberInfoType(MemberInfo memberInfo) /// /// All registered class maps. public static IEnumerable GetRegisteredClassMaps() => - BsonSerializer.DefaultDomain.BsonClassMap.GetRegisteredClassMaps(); + BsonSerializer.DefaultSerializationDomain.BsonClassMap.GetRegisteredClassMaps(); /// /// Checks whether a class map is registered for a type. @@ -286,7 +286,7 @@ public static IEnumerable GetRegisteredClassMaps() => /// The type to check. /// True if there is a class map registered for the type. public static bool IsClassMapRegistered(Type type) => - BsonSerializer.DefaultDomain.BsonClassMap.IsClassMapRegistered(type); + BsonSerializer.DefaultSerializationDomain.BsonClassMap.IsClassMapRegistered(type); /// /// Looks up a class map (will AutoMap the class if no class map is registered). @@ -294,7 +294,7 @@ public static bool IsClassMapRegistered(Type type) => /// The class type. /// The class map. public static BsonClassMap LookupClassMap(Type classType) => - BsonSerializer.DefaultDomain.BsonClassMap.LookupClassMap(classType); + BsonSerializer.DefaultSerializationDomain.BsonClassMap.LookupClassMap(classType); /// /// Creates and registers a class map. @@ -302,7 +302,7 @@ public static BsonClassMap LookupClassMap(Type classType) => /// The class. /// The class map. public static BsonClassMap RegisterClassMap()=> - BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(); + BsonSerializer.DefaultSerializationDomain.BsonClassMap.RegisterClassMap(); /// /// Creates and registers a class map. @@ -311,14 +311,14 @@ public static BsonClassMap RegisterClassMap()=> /// The class map initializer. /// The class map. public static BsonClassMap RegisterClassMap(Action> classMapInitializer) - => BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(classMapInitializer); + => BsonSerializer.DefaultSerializationDomain.BsonClassMap.RegisterClassMap(classMapInitializer); /// /// Registers a class map. /// /// The class map. public static void RegisterClassMap(BsonClassMap classMap) - => BsonSerializer.DefaultDomain.BsonClassMap.RegisterClassMap(classMap); + => BsonSerializer.DefaultSerializationDomain.BsonClassMap.RegisterClassMap(classMap); /// /// Registers a class map if it is not already registered. @@ -326,7 +326,7 @@ public static void RegisterClassMap(BsonClassMap classMap) /// The class. /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap() - => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(); + => BsonSerializer.DefaultSerializationDomain.BsonClassMap.TryRegisterClassMap(); /// /// Registers a class map if it is not already registered. @@ -335,7 +335,7 @@ public static bool TryRegisterClassMap() /// The class map. /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap(BsonClassMap classMap) - => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMap); + => BsonSerializer.DefaultSerializationDomain.BsonClassMap.TryRegisterClassMap(classMap); /// /// Registers a class map if it is not already registered. @@ -344,7 +344,7 @@ public static bool TryRegisterClassMap(BsonClassMap classMap) /// The class map initializer (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap(Action> classMapInitializer) - => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMapInitializer); + => BsonSerializer.DefaultSerializationDomain.BsonClassMap.TryRegisterClassMap(classMapInitializer); /// /// Registers a class map if it is not already registered. @@ -353,7 +353,7 @@ public static bool TryRegisterClassMap(Action> clas /// The class map factory (only called if the class map is not already registered). /// True if this call registered the class map, false if the class map was already registered. public static bool TryRegisterClassMap(Func> classMapFactory) - => BsonSerializer.DefaultDomain.BsonClassMap.TryRegisterClassMap(classMapFactory); + => BsonSerializer.DefaultSerializationDomain.BsonClassMap.TryRegisterClassMap(classMapFactory); // public methods /// @@ -416,7 +416,7 @@ internal class FreezeContext /// Freezes the class map. /// /// The frozen class map. - public BsonClassMap Freeze() => Freeze(BsonSerializer.DefaultDomain); + public BsonClassMap Freeze() => Freeze(BsonSerializer.DefaultSerializationDomain); internal BsonClassMap Freeze(IBsonSerializationDomain domain) { diff --git a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs index 7cb2f337ed7..ab47a273587 100644 --- a/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonDeserializationContext.cs @@ -28,7 +28,7 @@ public class BsonDeserializationContext private readonly IBsonSerializer _dynamicArraySerializer; private readonly IBsonSerializer _dynamicDocumentSerializer; private readonly IBsonReader _reader; - private readonly IBsonSerializationDomain _domain; + private readonly IBsonSerializationDomain _serializationDomain; // constructors private BsonDeserializationContext( @@ -41,7 +41,7 @@ private BsonDeserializationContext( _allowDuplicateElementNames = allowDuplicateElementNames; _dynamicArraySerializer = dynamicArraySerializer; _dynamicDocumentSerializer = dynamicDocumentSerializer; - _domain = reader.Settings?.SerializationDomain ?? BsonSerializer.DefaultDomain; + _serializationDomain = reader.Settings?.SerializationDomain ?? BsonSerializer.DefaultSerializationDomain; } // public properties @@ -59,7 +59,7 @@ public bool AllowDuplicateElementNames /// /// //TODO /// - public IBsonSerializationDomain Domain => _domain; + public IBsonSerializationDomain SerializationDomain => _serializationDomain; /// /// Gets the dynamic array serializer. @@ -145,7 +145,6 @@ public class Builder private IBsonSerializer _dynamicArraySerializer; private IBsonSerializer _dynamicDocumentSerializer; private IBsonReader _reader; - private IBsonSerializationDomain _domain; // constructors internal Builder(BsonDeserializationContext other, IBsonReader reader) @@ -161,7 +160,6 @@ internal Builder(BsonDeserializationContext other, IBsonReader reader) _allowDuplicateElementNames = other.AllowDuplicateElementNames; _dynamicArraySerializer = other.DynamicArraySerializer; _dynamicDocumentSerializer = other.DynamicDocumentSerializer; - _domain = other.Domain; } else { diff --git a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs index 81000bc917b..8374a3f906a 100644 --- a/src/MongoDB.Bson/Serialization/BsonMemberMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonMemberMap.cs @@ -294,7 +294,7 @@ obj is BsonMemberMap other && /// Gets the serializer. /// /// The serializer. - public IBsonSerializer GetSerializer() => GetSerializer(BsonSerializer.DefaultDomain); + public IBsonSerializer GetSerializer() => GetSerializer(BsonSerializer.DefaultSerializationDomain); /// /// //TODO diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs index 21a2524f179..b325f4d69aa 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationContext.cs @@ -26,7 +26,7 @@ public class BsonSerializationContext // private fields private readonly Func _isDynamicType; private readonly IBsonWriter _writer; - private readonly IBsonSerializationDomain _domain; + private readonly IBsonSerializationDomain _serializationDomain; // constructors private BsonSerializationContext( @@ -35,7 +35,7 @@ private BsonSerializationContext( { _writer = writer; _isDynamicType = isDynamicType; - _domain = writer.Settings?.SerializationDomain ?? BsonSerializer.DefaultDomain; + _serializationDomain = writer.Settings?.SerializationDomain ?? BsonSerializer.DefaultSerializationDomain; } // public properties @@ -43,7 +43,7 @@ private BsonSerializationContext( /// /// //TODO /// - public IBsonSerializationDomain Domain => _domain; + public IBsonSerializationDomain SerializationDomain => _serializationDomain; /// /// Gets a function that, when executed, will indicate whether the type diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index cea8aea6799..fd2a490fe04 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -26,32 +26,32 @@ namespace MongoDB.Bson.Serialization /// public static class BsonSerializer { - private static readonly IBsonSerializationDomainInternal _domain; + private static readonly IBsonSerializationDomainInternal _serializationDomain; // static constructor static BsonSerializer() { - _domain = new BsonSerializationDomain("MAIN"); + _serializationDomain = new BsonSerializationDomain("MAIN"); } /// /// //TODO /// - public static IBsonSerializationDomain DefaultDomain => _domain; + public static IBsonSerializationDomain DefaultSerializationDomain => _serializationDomain; // public static properties /// /// Gets the serializer registry. /// - public static IBsonSerializerRegistry SerializerRegistry => _domain.SerializerRegistry; + public static IBsonSerializerRegistry SerializerRegistry => _serializationDomain.SerializerRegistry; /// /// Gets or sets whether to use the NullIdChecker on reference Id types that don't have an IdGenerator registered. /// public static bool UseNullIdChecker { - get => _domain.UseNullIdChecker; - set => _domain.UseNullIdChecker = value; + get => _serializationDomain.UseNullIdChecker; + set => _serializationDomain.UseNullIdChecker = value; } /// @@ -59,12 +59,12 @@ public static bool UseNullIdChecker /// public static bool UseZeroIdChecker { - get => _domain.UseZeroIdChecker; - set => _domain.UseZeroIdChecker = value; + get => _serializationDomain.UseZeroIdChecker; + set => _serializationDomain.UseZeroIdChecker = value; } // internal static properties - internal static ReaderWriterLockSlim ConfigLock => _domain.ConfigLock; + internal static ReaderWriterLockSlim ConfigLock => _serializationDomain.ConfigLock; // public static methods @@ -82,7 +82,7 @@ public static bool UseZeroIdChecker /// The configurator. /// A deserialized value. public static TNominalType Deserialize(BsonDocument document, Action configurator = null) - => _domain.Deserialize(document, configurator); + => _serializationDomain.Deserialize(document, configurator); /// /// Deserializes a value. @@ -92,7 +92,7 @@ public static TNominalType Deserialize(BsonDocument document, Acti /// The configurator. /// A deserialized value. public static TNominalType Deserialize(IBsonReader bsonReader, Action configurator = null) - => _domain.Deserialize(bsonReader, configurator); + => _serializationDomain.Deserialize(bsonReader, configurator); /// /// Deserializes an object from a BSON byte array. @@ -102,7 +102,7 @@ public static TNominalType Deserialize(IBsonReader bsonReader, Act /// The configurator. /// A deserialized value. public static TNominalType Deserialize(byte[] bytes, Action configurator = null) - => _domain.Deserialize(bytes, configurator); + => _serializationDomain.Deserialize(bytes, configurator); /// /// Deserializes an object from a BSON Stream. @@ -112,7 +112,7 @@ public static TNominalType Deserialize(byte[] bytes, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(Stream stream, Action configurator = null) - => _domain.Deserialize(stream, configurator); + => _serializationDomain.Deserialize(stream, configurator); /// /// Deserializes an object from a JSON string. @@ -122,7 +122,7 @@ public static TNominalType Deserialize(Stream stream, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(string json, Action configurator = null) - => _domain.Deserialize(json, configurator); + => _serializationDomain.Deserialize(json, configurator); /// /// Deserializes an object from a JSON TextReader. @@ -132,7 +132,7 @@ public static TNominalType Deserialize(string json, ActionThe configurator. /// A deserialized value. public static TNominalType Deserialize(TextReader textReader, Action configurator = null) - => _domain.Deserialize(textReader, configurator); + => _serializationDomain.Deserialize(textReader, configurator); /// /// Deserializes an object from a BsonDocument. @@ -142,7 +142,7 @@ public static TNominalType Deserialize(TextReader textReader, Acti /// The configurator. /// A deserialized value. public static object Deserialize(BsonDocument document, Type nominalType, Action configurator = null) - => _domain.Deserialize(document, nominalType, configurator); + => _serializationDomain.Deserialize(document, nominalType, configurator); /// /// Deserializes a value. @@ -152,7 +152,7 @@ public static object Deserialize(BsonDocument document, Type nominalType, Action /// The configurator. /// A deserialized value. public static object Deserialize(IBsonReader bsonReader, Type nominalType, Action configurator = null) - => _domain.Deserialize(bsonReader, nominalType, configurator); + => _serializationDomain.Deserialize(bsonReader, nominalType, configurator); /// /// Deserializes an object from a BSON byte array. @@ -162,7 +162,7 @@ public static object Deserialize(IBsonReader bsonReader, Type nominalType, Actio /// The configurator. /// A deserialized value. public static object Deserialize(byte[] bytes, Type nominalType, Action configurator = null) - => _domain.Deserialize(bytes, nominalType, configurator); + => _serializationDomain.Deserialize(bytes, nominalType, configurator); /// /// Deserializes an object from a BSON Stream. @@ -172,7 +172,7 @@ public static object Deserialize(byte[] bytes, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(Stream stream, Type nominalType, Action configurator = null) - => _domain.Deserialize(stream, nominalType, configurator); + => _serializationDomain.Deserialize(stream, nominalType, configurator); /// /// Deserializes an object from a JSON string. @@ -182,7 +182,7 @@ public static object Deserialize(Stream stream, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(string json, Type nominalType, Action configurator = null) - => _domain.Deserialize(json, nominalType, configurator); + => _serializationDomain.Deserialize(json, nominalType, configurator); /// /// Deserializes an object from a JSON TextReader. @@ -192,13 +192,13 @@ public static object Deserialize(string json, Type nominalType, ActionThe configurator. /// A deserialized value. public static object Deserialize(TextReader textReader, Type nominalType, Action configurator = null) - => _domain.Deserialize(textReader, nominalType, configurator); + => _serializationDomain.Deserialize(textReader, nominalType, configurator); internal static IDiscriminatorConvention GetOrRegisterDiscriminatorConvention(Type type, IDiscriminatorConvention discriminatorConvention) - => _domain.GetOrRegisterDiscriminatorConvention(type, discriminatorConvention); + => _serializationDomain.GetOrRegisterDiscriminatorConvention(type, discriminatorConvention); internal static bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) - => _domain.IsDiscriminatorConventionRegisteredAtThisLevel(type); + => _serializationDomain.IsDiscriminatorConventionRegisteredAtThisLevel(type); /// /// Returns whether the given type has any discriminators registered for any of its subclasses. @@ -206,7 +206,7 @@ internal static bool IsDiscriminatorConventionRegisteredAtThisLevel(Type type) /// A Type. /// True if the type is discriminated. public static bool IsTypeDiscriminated(Type type) - => _domain.IsTypeDiscriminated(type); + => _serializationDomain.IsTypeDiscriminated(type); /// /// Looks up the actual type of an object to be deserialized. @@ -215,7 +215,7 @@ public static bool IsTypeDiscriminated(Type type) /// The discriminator. /// The actual type of the object. public static Type LookupActualType(Type nominalType, BsonValue discriminator) - => _domain.LookupActualType(nominalType, discriminator); + => _serializationDomain.LookupActualType(nominalType, discriminator); /// /// Looks up the discriminator convention for a type. @@ -223,7 +223,7 @@ public static Type LookupActualType(Type nominalType, BsonValue discriminator) /// The type. /// A discriminator convention. public static IDiscriminatorConvention LookupDiscriminatorConvention(Type type) - => _domain.LookupDiscriminatorConvention(type); + => _serializationDomain.LookupDiscriminatorConvention(type); /// /// Looks up an IdGenerator. @@ -231,21 +231,21 @@ public static IDiscriminatorConvention LookupDiscriminatorConvention(Type type) /// The Id type. /// An IdGenerator for the Id type. public static IIdGenerator LookupIdGenerator(Type type) - => _domain.LookupIdGenerator(type); + => _serializationDomain.LookupIdGenerator(type); /// /// Looks up a serializer for a Type. /// /// The type. /// A serializer for type T. - public static IBsonSerializer LookupSerializer() => _domain.LookupSerializer(); + public static IBsonSerializer LookupSerializer() => _serializationDomain.LookupSerializer(); /// /// Looks up a serializer for a Type. /// /// The Type. /// A serializer for the Type. - public static IBsonSerializer LookupSerializer(Type type) => _domain.LookupSerializer(type); + public static IBsonSerializer LookupSerializer(Type type) => _serializationDomain.LookupSerializer(type); /// /// Registers the discriminator for a type. @@ -253,7 +253,7 @@ public static IIdGenerator LookupIdGenerator(Type type) /// The type. /// The discriminator. public static void RegisterDiscriminator(Type type, BsonValue discriminator) - => _domain.RegisterDiscriminator(type, discriminator); + => _serializationDomain.RegisterDiscriminator(type, discriminator); /// /// Registers the discriminator convention for a type. @@ -261,7 +261,7 @@ public static void RegisterDiscriminator(Type type, BsonValue discriminator) /// Type type. /// The discriminator convention. public static void RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention) - => _domain.RegisterDiscriminatorConvention(type, convention); + => _serializationDomain.RegisterDiscriminatorConvention(type, convention); /// /// Registers a generic serializer definition for a generic type. @@ -269,7 +269,7 @@ public static void RegisterDiscriminatorConvention(Type type, IDiscriminatorConv /// The generic type. /// The generic serializer definition. public static void RegisterGenericSerializerDefinition(Type genericTypeDefinition, Type genericSerializerDefinition) - => _domain.RegisterGenericSerializerDefinition(genericTypeDefinition, genericSerializerDefinition); + => _serializationDomain.RegisterGenericSerializerDefinition(genericTypeDefinition, genericSerializerDefinition); /// /// Registers an IdGenerator for an Id Type. @@ -277,14 +277,14 @@ public static void RegisterGenericSerializerDefinition(Type genericTypeDefinitio /// The Id Type. /// The IdGenerator for the Id Type. public static void RegisterIdGenerator(Type type, IIdGenerator idGenerator) - => _domain.RegisterIdGenerator(type, idGenerator); + => _serializationDomain.RegisterIdGenerator(type, idGenerator); /// /// Registers a serialization provider. /// /// The serialization provider. public static void RegisterSerializationProvider(IBsonSerializationProvider provider) - => _domain.RegisterSerializationProvider(provider); + => _serializationDomain.RegisterSerializationProvider(provider); /// /// Registers a serializer for a type. @@ -292,7 +292,7 @@ public static void RegisterSerializationProvider(IBsonSerializationProvider prov /// The type. /// The serializer. public static void RegisterSerializer(IBsonSerializer serializer) - => _domain.RegisterSerializer(serializer); + => _serializationDomain.RegisterSerializer(serializer); /// /// Registers a serializer for a type. @@ -300,7 +300,7 @@ public static void RegisterSerializer(IBsonSerializer serializer) /// The type. /// The serializer. public static void RegisterSerializer(Type type, IBsonSerializer serializer) - => _domain.RegisterSerializer(type, serializer); + => _serializationDomain.RegisterSerializer(type, serializer); /// /// Serializes a value. @@ -315,7 +315,7 @@ public static void Serialize( TNominalType value, Action configurator = null, BsonSerializationArgs args = default) - => _domain.Serialize(bsonWriter, value, configurator, args); + => _serializationDomain.Serialize(bsonWriter, value, configurator, args); /// /// Serializes a value. @@ -331,7 +331,7 @@ public static void Serialize( object value, Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)) - => _domain.Serialize(bsonWriter, nominalType, value, configurator, args); + => _serializationDomain.Serialize(bsonWriter, nominalType, value, configurator, args); /// /// Tries to register a serializer for a type. @@ -340,7 +340,7 @@ public static void Serialize( /// The type. /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. public static bool TryRegisterSerializer(Type type, IBsonSerializer serializer) - => _domain.TryRegisterSerializer(type, serializer); + => _serializationDomain.TryRegisterSerializer(type, serializer); /// /// Tries to register a serializer for a type. @@ -349,10 +349,10 @@ public static bool TryRegisterSerializer(Type type, IBsonSerializer serializer) /// The serializer. /// True if the serializer was registered on this call, false if the same serializer was already registered on a previous call, throws an exception if a different serializer was already registered. public static bool TryRegisterSerializer(IBsonSerializer serializer) - => _domain.TryRegisterSerializer(serializer); + => _serializationDomain.TryRegisterSerializer(serializer); // internal static methods internal static void EnsureKnownTypesAreRegistered(Type nominalType) - => _domain.EnsureKnownTypesAreRegistered(nominalType); + => _serializationDomain.EnsureKnownTypesAreRegistered(nominalType); } } diff --git a/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs b/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs index dfdc8ddf8fa..ff80f900443 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs @@ -35,7 +35,7 @@ public sealed class BsonSerializerRegistry : IBsonSerializerRegistry /// Initializes a new instance of the class. /// public BsonSerializerRegistry(): - this(BsonSerializer.DefaultDomain) + this(BsonSerializer.DefaultSerializationDomain) { } diff --git a/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs b/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs index 13334d0280b..0799dd6c13f 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/AttributeConventionPack.cs @@ -87,7 +87,7 @@ public void Apply(BsonCreatorMap creatorMap) } } - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) { @@ -102,7 +102,7 @@ public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) } } - public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultSerializationDomain); public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) { diff --git a/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs index 7db675337ca..2a24166d4f9 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/CamelCaseElementNameConvention.cs @@ -25,7 +25,7 @@ public class CamelCaseElementNameConvention : ConventionBase, IMemberMapConventi { // public methods /// - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs index f2b46569615..3f9a9b5eb77 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/DelegateMemberMapConvention.cs @@ -46,7 +46,7 @@ public DelegateMemberMapConvention(string name, Action action) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs index efcee7f46c0..a8f11d061c7 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/DelegatePostProcessingConvention.cs @@ -46,7 +46,7 @@ public DelegatePostProcessingConvention(string name, Action action /// Applies a post processing modification to the class map. /// /// The class map. - public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultSerializationDomain); /// public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs index 49e18d31307..b2f5e5953d8 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs @@ -47,7 +47,7 @@ public EnumRepresentationConvention(BsonType representation) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs index 9b3cd73866e..d24210ff5b4 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs @@ -42,7 +42,7 @@ public HierarchicalDiscriminatorConvention(string elementName) /// The actual type. /// The discriminator value. public override BsonValue GetDiscriminator(Type nominalType, Type actualType) => - GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultDomain); + GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultSerializationDomain); /// public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs index 79dcc621fb9..a6b09d71019 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfDefaultConvention.cs @@ -37,7 +37,7 @@ public IgnoreIfDefaultConvention(bool ignoreIfDefault) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs index f2baec7dc91..6dfeaacf2d7 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/IgnoreIfNullConvention.cs @@ -37,7 +37,7 @@ public IgnoreIfNullConvention(bool ignoreIfNull) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs index 86df5fd2027..596983abe3b 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/LookupIdGeneratorConvention.cs @@ -24,7 +24,7 @@ namespace MongoDB.Bson.Serialization.Conventions public class LookupIdGeneratorConvention : ConventionBase, IPostProcessingConvention { /// - public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultSerializationDomain); /// public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs index 07440a28597..4a4bea208d7 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/MemberDefaultValueConvention.cs @@ -43,7 +43,7 @@ public MemberDefaultValueConvention(Type type, object defaultValue) /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs index 193282ef797..1a715e8991d 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/MemberNameElementNameConvention.cs @@ -28,7 +28,7 @@ public class MemberNameElementNameConvention : ConventionBase, IMemberMapConvent /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs index 49c62084468..4d47f56b750 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/NoIdMemberConvention.cs @@ -30,7 +30,7 @@ public class NoIdMemberConvention : ConventionBase, IPostProcessingConvention /// Applies a post processing modification to the class map. /// /// The class map. - public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultSerializationDomain); /// public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs index ca8e04da3ae..63c9d91df20 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ObjectDiscriminatorConvention.cs @@ -87,7 +87,7 @@ obj is ObjectDiscriminatorConvention other && /// The nominal type. /// The actual type. public Type GetActualType(IBsonReader bsonReader, Type nominalType) => - GetActualType(bsonReader, nominalType, BsonSerializer.DefaultDomain); + GetActualType(bsonReader, nominalType, BsonSerializer.DefaultSerializationDomain); /// public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs index af1d0eedf6b..96d5117905b 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ObjectSerializerAllowedTypesConvention.cs @@ -150,7 +150,7 @@ public bool AllowDefaultFrameworkTypes /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs index 5971f97d32c..81ff334c553 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ResetMemberMapsConvention.cs @@ -25,7 +25,7 @@ public class ResetMemberMapsConvention : ConventionBase, IMemberMapConvention /// Applies a modification to the member map. /// /// The member map. - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs index 6045ac80a1b..e8fba249a7d 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ScalarDiscriminatorConvention.cs @@ -40,7 +40,7 @@ public ScalarDiscriminatorConvention(string elementName) /// The actual type. /// The discriminator value. public override BsonValue GetDiscriminator(Type nominalType, Type actualType) => - GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultDomain); + GetDiscriminator(nominalType, actualType, BsonSerializer.DefaultSerializationDomain); /// public override BsonValue GetDiscriminator(Type nominalType, Type actualType, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs index 071d624c7a5..85c2226cd99 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StandardDiscriminatorConvention.cs @@ -95,7 +95,7 @@ obj is StandardDiscriminatorConvention other && /// The nominal type. /// The actual type. public Type GetActualType(IBsonReader bsonReader, Type nominalType) => - GetActualType(bsonReader, nominalType, BsonSerializer.DefaultDomain); + GetActualType(bsonReader, nominalType, BsonSerializer.DefaultSerializationDomain); /// public Type GetActualType(IBsonReader bsonReader, Type nominalType, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs index a6b3e108095..2671ca18107 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs @@ -26,7 +26,7 @@ namespace MongoDB.Bson.Serialization.Conventions public class StringIdStoredAsObjectIdConvention : ConventionBase, IMemberMapConvention { /// - public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultDomain); + public void Apply(BsonMemberMap memberMap) => Apply(memberMap, BsonSerializer.DefaultSerializationDomain); /// public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs index 9ea6db46264..ebcacdf76b5 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StringObjectIdIdGeneratorConvention.cs @@ -29,7 +29,7 @@ public class StringObjectIdIdGeneratorConvention : ConventionBase, IPostProcessi /// Applies a post processing modification to the class map. /// /// The class map. - public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultDomain); + public void PostProcess(BsonClassMap classMap) => PostProcess(classMap, BsonSerializer.DefaultSerializationDomain); /// public void PostProcess(BsonClassMap classMap, IBsonSerializationDomain domain) diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs index 9ef3c9acf49..a509e6ee17a 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs @@ -96,7 +96,7 @@ public override TClass Deserialize(BsonDeserializationContext context, BsonDeser return DeserializeClass(context); } - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); return (TClass)serializer.Deserialize(context); } @@ -326,7 +326,7 @@ public bool GetDocumentId( out object id, out Type idNominalType, out IIdGenerator idGenerator) - => GetDocumentId(document, BsonSerializer.DefaultDomain, out id, out idNominalType, out idGenerator); + => GetDocumentId(document, BsonSerializer.DefaultSerializationDomain, out id, out idNominalType, out idGenerator); /// public bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType, @@ -397,7 +397,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati return; } - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); serializer.Serialize(context, args, value); } @@ -571,7 +571,7 @@ private object DeserializeMemberValue(BsonDeserializationContext context, BsonMe { try { - return memberMap.GetSerializer(context.Domain).Deserialize(context); + return memberMap.GetSerializer(context.SerializationDomain).Deserialize(context); } catch (Exception ex) { @@ -689,7 +689,7 @@ private void SerializeNormalMember(BsonSerializationContext context, object obj, } bsonWriter.WriteName(memberMap.ElementName); - memberMap.GetSerializer(context.Domain).Serialize(context, value); + memberMap.GetSerializer(context.SerializationDomain).Serialize(context, value); } private bool ShouldSerializeDiscriminator(Type nominalType) diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs index 465f312db0a..34657599b2e 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonDocumentSerializer.cs @@ -81,7 +81,7 @@ public bool GetDocumentId( object document, out object id, out Type idNominalType, - out IIdGenerator idGenerator) => GetDocumentId(document, BsonSerializer.DefaultDomain, out id, + out IIdGenerator idGenerator) => GetDocumentId(document, BsonSerializer.DefaultSerializationDomain, out id, out idNominalType, out idGenerator); /// diff --git a/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs index 4373f7b0543..0f636ae834b 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/BsonValueSerializerBase.cs @@ -70,7 +70,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati var actualType = value.GetType(); if (actualType != ValueType && !args.SerializeAsNominalType) { - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); serializer.Serialize(context, value); return; } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs b/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs index 39ac5184e9c..963d97655ef 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ClassSerializerBase.cs @@ -47,7 +47,7 @@ public override TValue Deserialize(BsonDeserializationContext context, BsonDeser } else { - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); return (TValue)serializer.Deserialize(context, args); } } @@ -75,7 +75,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati } else { - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); serializer.Serialize(context, value); } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs index ea38dd969f9..66a1a0e753a 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs @@ -87,7 +87,7 @@ public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorCo /// interfaceType /// interfaceType public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorConvention, IBsonSerializer interfaceSerializer) - : this(discriminatorConvention, interfaceSerializer, BsonSerializer.DefaultDomain) + : this(discriminatorConvention, interfaceSerializer, BsonSerializer.DefaultSerializationDomain) { } @@ -162,7 +162,7 @@ public override TInterface Deserialize(BsonDeserializationContext context, BsonD throw new FormatException(message); } - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); return (TInterface)serializer.Deserialize(context, args); } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs index da40cf24480..e1d52bd9e0c 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedWrapperSerializer.cs @@ -74,7 +74,7 @@ public override TValue Deserialize(BsonDeserializationContext context, BsonDeser var bsonReader = context.Reader; var nominalType = args.NominalType; var actualType = _discriminatorConvention.GetActualType(bsonReader, nominalType); - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); TValue value = default(TValue); _helper.DeserializeMembers(context, (elementName, flag) => diff --git a/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs index f85e7c2e17e..84f14ac3493 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs @@ -58,7 +58,7 @@ public override T Deserialize(BsonDeserializationContext context, BsonDeserializ while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { var name = bsonReader.ReadName(); - var value = GetObjectSerializer(context.Domain).Deserialize(dynamicContext); + var value = GetObjectSerializer(context.SerializationDomain).Deserialize(dynamicContext); SetValueForMember(document, name, value); } bsonReader.ReadEndDocument(); @@ -101,7 +101,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati if (TryGetValueForMember(value, memberName, out memberValue)) { bsonWriter.WriteName(memberName); - GetObjectSerializer(context.Domain).Serialize(dynamicContext, memberValue); + GetObjectSerializer(context.SerializationDomain).Serialize(dynamicContext, memberValue); } } bsonWriter.WriteEndDocument(); diff --git a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs index 8081bee4bbe..4491cfdfe36 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ExpandoObjectSerializer.cs @@ -35,7 +35,7 @@ public sealed class ExpandoObjectSerializer : DynamicDocumentBaseSerializer class. /// public ExpandoObjectSerializer() - :this(BsonSerializer.DefaultDomain.SerializerRegistry) + :this(BsonSerializer.DefaultSerializationDomain.SerializerRegistry) { } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs index fc128f6e17b..988127b8fa4 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ImpliedImplementationInterfaceSerializer.cs @@ -279,7 +279,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati } else { - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); serializer.Serialize(context, value); } } diff --git a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs index e1416c7cd50..8afcac9d601 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ObjectSerializer.cs @@ -389,7 +389,7 @@ private object DeserializeDiscriminatedValue(BsonDeserializationContext context, } else { - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); var polymorphicSerializer = serializer as IBsonPolymorphicSerializer; if (polymorphicSerializer != null && polymorphicSerializer.IsDiscriminatorCompatibleWithObjectSerializer) { @@ -438,7 +438,7 @@ private void SerializeDiscriminatedValue(BsonSerializationContext context, BsonS throw new BsonSerializationException($"Type {actualType.FullName} is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer."); } - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); var polymorphicSerializer = serializer as IBsonPolymorphicSerializer; if (polymorphicSerializer != null && polymorphicSerializer.IsDiscriminatorCompatibleWithObjectSerializer) diff --git a/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs index 8d843ba16de..240ac575b1b 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/UndiscriminatedActualTypeSerializer.cs @@ -62,7 +62,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati else { var actualType = value.GetType(); - var serializer = context.Domain.LookupSerializer(actualType); + var serializer = context.SerializationDomain.LookupSerializer(actualType); args.NominalType = actualType; serializer.Serialize(context, args, value); } diff --git a/src/MongoDB.Driver/MongoClientSettings.cs b/src/MongoDB.Driver/MongoClientSettings.cs index d0c012adbbb..99de0b9d5ad 100644 --- a/src/MongoDB.Driver/MongoClientSettings.cs +++ b/src/MongoDB.Driver/MongoClientSettings.cs @@ -119,7 +119,7 @@ public MongoClientSettings() _retryReads = true; _retryWrites = true; _scheme = ConnectionStringScheme.MongoDB; - _serializationDomain = BsonSerializer.DefaultDomain; + _serializationDomain = BsonSerializer.DefaultSerializationDomain; _serverApi = null; _servers = new List { new MongoServerAddress("localhost") }; _serverMonitoringMode = ServerMonitoringMode.Auto; diff --git a/src/MongoDB.Driver/OfTypeSerializer.cs b/src/MongoDB.Driver/OfTypeSerializer.cs index a95c2f1a22f..ae63608cb97 100644 --- a/src/MongoDB.Driver/OfTypeSerializer.cs +++ b/src/MongoDB.Driver/OfTypeSerializer.cs @@ -47,7 +47,7 @@ obj is OfTypeSerializer other && public bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) - => GetDocumentId(document, BsonSerializer.DefaultDomain, out id, out idNominalType, out idGenerator); + => GetDocumentId(document, BsonSerializer.DefaultSerializationDomain, out id, out idNominalType, out idGenerator); public bool GetDocumentId(object document, IBsonSerializationDomain domain, out object id, out Type idNominalType, out IIdGenerator idGenerator) From 2ed6fb69da7caa314489b3d33565d925038ebdec Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 10 Feb 2025 17:11:52 +0100 Subject: [PATCH 45/49] Small naming correction --- src/MongoDB.Bson/Serialization/BsonSerializer.cs | 2 +- tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializer.cs b/src/MongoDB.Bson/Serialization/BsonSerializer.cs index fd2a490fe04..cfb0f44d356 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializer.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializer.cs @@ -72,7 +72,7 @@ public static bool UseZeroIdChecker /// //TODO /// /// - public static IBsonSerializationDomain CreateDomain() => new BsonSerializationDomain(); + public static IBsonSerializationDomain CreateSerializationDomain() => new BsonSerializationDomain(); /// /// Deserializes an object from a BsonDocument. diff --git a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs index 5e52613ca68..b65265abb08 100644 --- a/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs +++ b/tests/MongoDB.Driver.Tests/MultipleRegistriesTests.cs @@ -49,7 +49,7 @@ public void TestSerialization() //The first section demonstrates that the class maps are also separated { - var customDomain = BsonSerializer.CreateDomain(); + var customDomain = BsonSerializer.CreateSerializationDomain(); customDomain.RegisterSerializer(new CustomStringSerializer()); var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = customDomain); @@ -88,7 +88,7 @@ public void TestDeserialization() } { - var customDomain = BsonSerializer.CreateDomain(); + var customDomain = BsonSerializer.CreateSerializationDomain(); customDomain.RegisterSerializer(new CustomStringSerializer()); var client = DriverTestConfiguration.CreateMongoClient(c => c.SerializationDomain = customDomain); From 0074837394d620fdb80d7dfaff44a40a5b789bf9 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 10 Feb 2025 17:13:14 +0100 Subject: [PATCH 46/49] Fixed tests --- src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs | 6 +++--- src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs | 1 - tests/MongoDB.Driver.Tests/AggregateFluentTests.cs | 1 + tests/MongoDB.Driver.Tests/FindFluentTests.cs | 1 + .../MongoDB.Driver.Tests/IAggregateFluentExtensionsTests.cs | 1 + .../MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs | 2 ++ 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 5b4d544886e..16c759df494 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -30,8 +30,8 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp // ConcurrentDictionary is being used as a concurrent set of Type. The values will always be null. private ConcurrentDictionary _typesWithRegisteredKnownTypes = new(); - private bool _useNullIdChecker = false; - private bool _useZeroIdChecker = false; + private bool _useNullIdChecker; + private bool _useZeroIdChecker; // constructor public BsonSerializationDomain(string name = null) //TODO name is used for testing @@ -39,7 +39,7 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp CreateSerializerRegistry(); RegisterIdGenerators(); _classMapDomain = new BsonClassMapDomain(); - Name = name ?? "CUSTOM"; + Name = name ?? "CUSTOM"; //TODO remove after testing is done } public string Name { get; private set; } diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index fe97dbe6063..61a761a8de9 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -284,7 +284,6 @@ void Serialize( Action configurator = null, BsonSerializationArgs args = default(BsonSerializationArgs)); - /// /// //TODO /// diff --git a/tests/MongoDB.Driver.Tests/AggregateFluentTests.cs b/tests/MongoDB.Driver.Tests/AggregateFluentTests.cs index 2beef58b39e..f529aeace37 100644 --- a/tests/MongoDB.Driver.Tests/AggregateFluentTests.cs +++ b/tests/MongoDB.Driver.Tests/AggregateFluentTests.cs @@ -1327,6 +1327,7 @@ private Mock> CreateMockCollection(IMongoDatabase database = var collectionNamespace = new CollectionNamespace(databaseNamespace, collectionName); var settings = new MongoCollectionSettings(); + settings.SerializationDomain = BsonSerializer.CreateSerializationDomain(); var mockCollection = new Mock>(); mockCollection.SetupGet(c => c.CollectionNamespace).Returns(collectionNamespace); mockCollection.SetupGet(c => c.Database).Returns(database); diff --git a/tests/MongoDB.Driver.Tests/FindFluentTests.cs b/tests/MongoDB.Driver.Tests/FindFluentTests.cs index fb70cd6f43c..ffd87468d0e 100644 --- a/tests/MongoDB.Driver.Tests/FindFluentTests.cs +++ b/tests/MongoDB.Driver.Tests/FindFluentTests.cs @@ -359,6 +359,7 @@ private IFindFluent CreateSubject(IClientSessionHandle session = mockDatabase.SetupGet(d => d.Client).Returns(mockClient.Object); var collectionSettings = new MongoCollectionSettings(); + collectionSettings.SerializationDomain = BsonSerializer.CreateSerializationDomain(); _mockCollection = new Mock>(); _mockCollection.SetupGet(c => c.Database).Returns(mockDatabase.Object); _mockCollection.SetupGet(c => c.DocumentSerializer).Returns(BsonSerializer.SerializerRegistry.GetSerializer()); diff --git a/tests/MongoDB.Driver.Tests/IAggregateFluentExtensionsTests.cs b/tests/MongoDB.Driver.Tests/IAggregateFluentExtensionsTests.cs index 5094dbfa2b7..13351c9f913 100644 --- a/tests/MongoDB.Driver.Tests/IAggregateFluentExtensionsTests.cs +++ b/tests/MongoDB.Driver.Tests/IAggregateFluentExtensionsTests.cs @@ -671,6 +671,7 @@ private IMongoCollection CreateCollection(string collectionName = null) { var database = CreateDatabase(); var settings = new MongoCollectionSettings(); + settings.SerializationDomain = BsonSerializer.CreateSerializationDomain(); var mockCollection = new Mock>(); mockCollection.SetupGet(c => c.CollectionNamespace).Returns(new CollectionNamespace(new DatabaseNamespace("test"), collectionName ?? typeof(T).Name)); mockCollection.SetupGet(c => c.Database).Returns(database); diff --git a/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs b/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs index a65cf915b5c..d2dd5750ec1 100644 --- a/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs +++ b/tests/MongoDB.Driver.Tests/IMongoCollectionExtensionsTests.cs @@ -20,6 +20,7 @@ using System.Threading; using FluentAssertions; using MongoDB.Bson; +using MongoDB.Bson.Serialization; using MongoDB.Driver.Tests.Linq.Linq3Implementation; using MongoDB.TestHelpers.XunitExtensions; using Moq; @@ -1376,6 +1377,7 @@ private Mock> CreateMockCollection() var mockCollection = new Mock> { DefaultValue = DefaultValue.Mock }; mockCollection.SetupGet(c => c.Database).Returns(mockDatabase.Object); var collectionSettings = new MongoCollectionSettings(); + collectionSettings.SerializationDomain = BsonSerializer.CreateSerializationDomain(); mockCollection.SetupGet(s => s.DocumentSerializer).Returns(collectionSettings.SerializerRegistry.GetSerializer()); mockCollection.SetupGet(s => s.Settings).Returns(collectionSettings); From 9011589a8f14f575f6456de5a9d6398f4931f7a5 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:58:57 +0100 Subject: [PATCH 47/49] removed comment --- .../Conventions/StringIdStoredAsObjectIdConvention.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs index 2671ca18107..64ae3ea628b 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/StringIdStoredAsObjectIdConvention.cs @@ -41,7 +41,7 @@ public void Apply(BsonMemberMap memberMap, IBsonSerializationDomain domain) return; } - var defaultStringSerializer = domain.LookupSerializer(typeof(string)); //TODO ?? + var defaultStringSerializer = domain.LookupSerializer(typeof(string)); if (memberMap.GetSerializer() != defaultStringSerializer) { return; From 8b1544567c32d19dc97843200711e05e2830a238 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 12 Feb 2025 14:33:20 +0100 Subject: [PATCH 48/49] Added convention registry --- .../Serialization/BsonSerializationDomain.cs | 4 + .../Conventions/ConventionRegistry.cs | 104 +-------------- .../Conventions/ConventionRegistryDomain.cs | 126 ++++++++++++++++++ .../Conventions/IConventionRegistryDomain.cs | 31 +++++ .../Serialization/IBsonSerializationDomain.cs | 5 + 5 files changed, 173 insertions(+), 97 deletions(-) create mode 100644 src/MongoDB.Bson/Serialization/Conventions/ConventionRegistryDomain.cs create mode 100644 src/MongoDB.Bson/Serialization/Conventions/IConventionRegistryDomain.cs diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index 16c759df494..fef52a44fa8 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -20,6 +20,7 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp // private fields private ReaderWriterLockSlim _configLock = new(LockRecursionPolicy.SupportsRecursion); private IBsonClassMapDomain _classMapDomain; + private IConventionRegistryDomain _conventionRegistryDomain; private Dictionary _idGenerators = new(); private Dictionary _discriminatorConventions = new(); private Dictionary> _discriminators = new(); @@ -39,6 +40,7 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp CreateSerializerRegistry(); RegisterIdGenerators(); _classMapDomain = new BsonClassMapDomain(); + _conventionRegistryDomain = new ConventionRegistryDomain(); Name = name ?? "CUSTOM"; //TODO remove after testing is done } @@ -734,6 +736,8 @@ public void Serialize( public IBsonClassMapDomain BsonClassMap => _classMapDomain; + public IConventionRegistryDomain ConventionRegistry => _conventionRegistryDomain; + /// /// Tries to register a serializer for a type. /// diff --git a/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs b/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs index a938faf3884..582693d64e4 100644 --- a/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs +++ b/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistry.cs @@ -14,69 +14,22 @@ */ using System; -using System.Collections.Generic; namespace MongoDB.Bson.Serialization.Conventions { /// /// Represents a registry of conventions. /// - public static class ConventionRegistry //TODO Probably this should get the same treatment as BsonSerializer.... + public static class ConventionRegistry { - // private static fields - private readonly static List __conventionPacks = new List(); - private readonly static object __lock = new object(); - - // static constructors - static ConventionRegistry() - { - Register("__defaults__", DefaultConventionPack.Instance, t => true); - Register("__attributes__", AttributeConventionPack.Instance, t => true); - } - // public static methods /// /// Looks up the effective set of conventions that apply to a type. /// /// The type. /// The conventions for that type. - public static IConventionPack Lookup(Type type) - { - if (type == null) - { - throw new ArgumentNullException("type"); - } - - lock (__lock) - { - var pack = new ConventionPack(); - - // append any attribute packs (usually just one) at the end so attributes are processed last - var attributePacks = new List(); - foreach (var container in __conventionPacks) - { - if (container.Filter(type)) - { - - if (container.Name == "__attributes__") - { - attributePacks.Add(container.Pack); - } - else - { - pack.Append(container.Pack); - } - } - } - - foreach (var attributePack in attributePacks) - { - pack.Append(attributePack); - } - - return pack; - } - } + public static IConventionPack Lookup(Type type) => + BsonSerializer.DefaultSerializationDomain.ConventionRegistry.Lookup(type); /// /// Registers the conventions. @@ -84,33 +37,8 @@ public static IConventionPack Lookup(Type type) /// The name. /// The conventions. /// The filter. - public static void Register(string name, IConventionPack conventions, Func filter) - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - if (conventions == null) - { - throw new ArgumentNullException("conventions"); - } - if (filter == null) - { - throw new ArgumentNullException("filter"); - } - - lock (__lock) - { - var container = new ConventionPackContainer - { - Filter = filter, - Name = name, - Pack = conventions - }; - - __conventionPacks.Add(container); - } - } + public static void Register(string name, IConventionPack conventions, Func filter) => + BsonSerializer.DefaultSerializationDomain.ConventionRegistry.Register(name, conventions, filter); /// /// Removes the conventions specified by the given name. @@ -119,25 +47,7 @@ public static void Register(string name, IConventionPack conventions, FuncRemoving a convention allows the removal of the special __defaults__ conventions /// and the __attributes__ conventions for those who want to completely customize the /// experience. - public static void Remove(string name) - { - if (name == null) - { - throw new ArgumentNullException("name"); - } - - lock (__lock) - { - __conventionPacks.RemoveAll(x => x.Name == name); - } - } - - // private class - private class ConventionPackContainer - { - public Func Filter; - public string Name; - public IConventionPack Pack; - } + public static void Remove(string name) => + BsonSerializer.DefaultSerializationDomain.ConventionRegistry.Remove(name); } } diff --git a/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistryDomain.cs b/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistryDomain.cs new file mode 100644 index 00000000000..3bf5a4935fe --- /dev/null +++ b/src/MongoDB.Bson/Serialization/Conventions/ConventionRegistryDomain.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; + +namespace MongoDB.Bson.Serialization.Conventions +{ + internal class ConventionRegistryDomain : IConventionRegistryDomain + { + private readonly List _conventionPacks = []; + private readonly object _lock = new(); + + // constructors + internal ConventionRegistryDomain() + { + Register("__defaults__", DefaultConventionPack.Instance, t => true); + Register("__attributes__", AttributeConventionPack.Instance, t => true); + } + + // public static methods + /// + /// Looks up the effective set of conventions that apply to a type. + /// + /// The type. + /// The conventions for that type. + public IConventionPack Lookup(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + lock (_lock) + { + var pack = new ConventionPack(); + + // append any attribute packs (usually just one) at the end so attributes are processed last + var attributePacks = new List(); + foreach (var container in _conventionPacks) + { + if (container.Filter(type)) + { + + if (container.Name == "__attributes__") + { + attributePacks.Add(container.Pack); + } + else + { + pack.Append(container.Pack); + } + } + } + + foreach (var attributePack in attributePacks) + { + pack.Append(attributePack); + } + + return pack; + } + } + + /// + /// Registers the conventions. + /// + /// The name. + /// The conventions. + /// The filter. + public void Register(string name, IConventionPack conventions, Func filter) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + if (conventions == null) + { + throw new ArgumentNullException("conventions"); + } + + if (filter == null) + { + throw new ArgumentNullException("filter"); + } + + lock (_lock) + { + var container = new ConventionPackContainer + { + Filter = filter, + Name = name, + Pack = conventions + }; + + _conventionPacks.Add(container); + } + } + + /// + /// Removes the conventions specified by the given name. + /// + /// The name. + /// Removing a convention allows the removal of the special __defaults__ conventions + /// and the __attributes__ conventions for those who want to completely customize the + /// experience. + public void Remove(string name) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + lock (_lock) + { + _conventionPacks.RemoveAll(x => x.Name == name); + } + } + + // private class + private class ConventionPackContainer + { + public Func Filter; + public string Name; + public IConventionPack Pack; + } + } +} \ No newline at end of file diff --git a/src/MongoDB.Bson/Serialization/Conventions/IConventionRegistryDomain.cs b/src/MongoDB.Bson/Serialization/Conventions/IConventionRegistryDomain.cs new file mode 100644 index 00000000000..d7ff791518d --- /dev/null +++ b/src/MongoDB.Bson/Serialization/Conventions/IConventionRegistryDomain.cs @@ -0,0 +1,31 @@ +using System; + +namespace MongoDB.Bson.Serialization.Conventions +{ + /// + /// //TODO + /// + public interface IConventionRegistryDomain + { + /// + /// //TODO + /// + /// + /// + IConventionPack Lookup(Type type); + + /// + /// //TODO + /// + /// + /// + /// + void Register(string name, IConventionPack conventions, Func filter); + + /// + /// //TODO + /// + /// + void Remove(string name); + } +} \ No newline at end of file diff --git a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs index 61a761a8de9..7885b5b0be0 100644 --- a/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/IBsonSerializationDomain.cs @@ -288,6 +288,11 @@ void Serialize( /// //TODO /// IBsonClassMapDomain BsonClassMap { get; } + + /// + /// //TODO + /// + IConventionRegistryDomain ConventionRegistry { get; } } internal interface IBsonSerializationDomainInternal : IBsonSerializationDomain From 2157ae81dafdeea383e0a6ef34abf7cdaa770a33 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Wed, 12 Feb 2025 15:29:44 +0100 Subject: [PATCH 49/49] Some improvements --- .../Serialization/BsonClassMap.cs | 25 ++++++++----------- .../Serialization/BsonClassMapDomain.cs | 16 ++++++++---- .../Serialization/BsonSerializationDomain.cs | 9 +++++-- .../DiscriminatedInterfaceSerializer.cs | 2 +- ...essionToAggregationExpressionTranslator.cs | 8 +++--- .../Translators/TranslationContext.cs | 6 ++++- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 061e7702a39..e14b55c8ea5 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -34,7 +34,6 @@ public class BsonClassMap // private fields private readonly Type _classType; private readonly List _creatorMaps; - private readonly IConventionPack _conventionPack; private readonly bool _isAnonymous; private readonly List _allMemberMaps; // includes inherited member maps private readonly ReadOnlyCollection _allMemberMapsReadonly; @@ -65,7 +64,6 @@ public BsonClassMap(Type classType) { _classType = classType; _creatorMaps = new List(); - _conventionPack = ConventionRegistry.Lookup(classType); _isAnonymous = classType.IsAnonymousType(); _allMemberMaps = new List(); _allMemberMapsReadonly = _allMemberMaps.AsReadOnly(); @@ -119,14 +117,6 @@ public IEnumerable CreatorMaps get { return _creatorMaps; } } - /// - /// Gets the conventions used for auto mapping. - /// - public IConventionPack ConventionPack - { - get { return _conventionPack; } - } - /// /// Gets the declared member maps (only for members declared in this class). /// @@ -359,10 +349,16 @@ public static bool TryRegisterClassMap(Func> classM /// /// Automaps the class. /// - public void AutoMap() + public void AutoMap() => AutoMap(BsonSerializer.DefaultSerializationDomain); + + /// + /// //TODO + /// + /// + public void AutoMap(IBsonSerializationDomain serializationDomain) { if (_frozen) { ThrowFrozenException(); } - AutoMapClass(); + AutoMapClass(serializationDomain); } /// @@ -1208,9 +1204,10 @@ IDiscriminatorConvention LookupDiscriminatorConvention() } // private methods - private void AutoMapClass() + private void AutoMapClass(IBsonSerializationDomain serializationDomain) { - new ConventionRunner(_conventionPack).Apply(this); + var conventionPack = serializationDomain.ConventionRegistry.Lookup(_classType); + new ConventionRunner(conventionPack).Apply(this); foreach (var memberMap in _declaredMemberMaps) { diff --git a/src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs b/src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs index 3651bf782a6..7732ac9742e 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMapDomain.cs @@ -8,8 +8,14 @@ namespace MongoDB.Bson.Serialization; internal class BsonClassMapDomain : IBsonClassMapDomain { // private fields + private readonly IBsonSerializationDomain _serializationDomain; private readonly Dictionary _classMaps = new(); + public BsonClassMapDomain(BsonSerializationDomain serializationDomain) + { + _serializationDomain = serializationDomain; + } + /// /// Gets all registered class maps. /// @@ -83,7 +89,7 @@ public BsonClassMap LookupClassMap(Type classType) var classMapDefinition = typeof(BsonClassMap<>); var classMapType = classMapDefinition.MakeGenericType(classType); var newClassMap = (BsonClassMap)Activator.CreateInstance(classMapType); - newClassMap.AutoMap(); + newClassMap.AutoMap(_serializationDomain); BsonSerializer.ConfigLock.EnterWriteLock(); try @@ -109,7 +115,7 @@ public BsonClassMap LookupClassMap(Type classType) /// The class map. public BsonClassMap RegisterClassMap() { - return RegisterClassMap(cm => { cm.AutoMap(); }); + return RegisterClassMap(cm => { cm.AutoMap(_serializationDomain); }); } /// @@ -156,12 +162,12 @@ public void RegisterClassMap(BsonClassMap classMap) /// True if this call registered the class map, false if the class map was already registered. public bool TryRegisterClassMap() { - return TryRegisterClassMap(ClassMapFactory); + return TryRegisterClassMap(() => ClassMapFactory(_serializationDomain)); - static BsonClassMap ClassMapFactory() + static BsonClassMap ClassMapFactory(IBsonSerializationDomain serializationDomain) { var classMap = new BsonClassMap(); - classMap.AutoMap(); + classMap.AutoMap(serializationDomain); return classMap; } } diff --git a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs index fef52a44fa8..8a4c89b246b 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializationDomain.cs @@ -38,9 +38,8 @@ internal class BsonSerializationDomain : IBsonSerializationDomainInternal, IDisp public BsonSerializationDomain(string name = null) //TODO name is used for testing { CreateSerializerRegistry(); + CreateSubDomains(); RegisterIdGenerators(); - _classMapDomain = new BsonClassMapDomain(); - _conventionRegistryDomain = new ConventionRegistryDomain(); Name = name ?? "CUSTOM"; //TODO remove after testing is done } @@ -815,6 +814,12 @@ private void CreateSerializerRegistry() _serializerRegistry.RegisterSerializationProvider(new BsonObjectModelSerializationProvider()); } + private void CreateSubDomains() + { + _classMapDomain = new BsonClassMapDomain(this); + _conventionRegistryDomain = new ConventionRegistryDomain(); + } + private void RegisterIdGenerators() { RegisterIdGenerator(typeof(BsonObjectId), BsonObjectIdGenerator.Instance); diff --git a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs index 66a1a0e753a..2ace50407f1 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DiscriminatedInterfaceSerializer.cs @@ -46,7 +46,7 @@ private static IBsonSerializer CreateInterfaceSerializer(IBsonSerial var classMapDefinition = typeof(BsonClassMap<>); var classMapType = classMapDefinition.MakeGenericType(typeof(TInterface)); var classMap = (BsonClassMap)Activator.CreateInstance(classMapType); - classMap.AutoMap(); + classMap.AutoMap(domain); classMap.SetDiscriminatorConvention(domain.LookupDiscriminatorConvention(typeof(TInterface))); classMap.Freeze(domain); return new BsonClassMapSerializer(classMap); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MemberInitExpressionToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MemberInitExpressionToAggregationExpressionTranslator.cs index e1a8cd5f399..54f832de95a 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MemberInitExpressionToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MemberInitExpressionToAggregationExpressionTranslator.cs @@ -47,7 +47,7 @@ public static AggregationExpression Translate( var constructorInfo = newExpression.Constructor; // note: can be null when using the default constructor with a struct var constructorArguments = newExpression.Arguments; var computedFields = new List(); - var classMap = CreateClassMap(newExpression.Type, constructorInfo, out var creatorMap); + var classMap = CreateClassMap(context, newExpression.Type, constructorInfo, out var creatorMap); if (constructorInfo != null && creatorMap != null) { @@ -100,12 +100,12 @@ public static AggregationExpression Translate( return new AggregationExpression(expression, ast, serializer); } - private static BsonClassMap CreateClassMap(Type classType, ConstructorInfo constructorInfo, out BsonCreatorMap creatorMap) + private static BsonClassMap CreateClassMap(TranslationContext context, Type classType, ConstructorInfo constructorInfo, out BsonCreatorMap creatorMap) { BsonClassMap baseClassMap = null; if (classType.BaseType != null) { - baseClassMap = CreateClassMap(classType.BaseType, null, out _); + baseClassMap = CreateClassMap(context, classType.BaseType, null, out _); } var classMapType = typeof(BsonClassMap<>).MakeGenericType(classType); @@ -120,7 +120,7 @@ private static BsonClassMap CreateClassMap(Type classType, ConstructorInfo const creatorMap = null; } - classMap.AutoMap(); + classMap.AutoMap(context.SerializationDomain); classMap.IdMemberMap?.SetElementName("_id"); // normally happens when Freeze is called but we need it sooner here return classMap; diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs index 55629aac049..f15f4397551 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs @@ -32,13 +32,14 @@ public static TranslationContext Create( { var symbolTable = new SymbolTable(); var nameGenerator = new NameGenerator(); - return new TranslationContext(symbolTable, nameGenerator, translationOptions, data); + return new TranslationContext(symbolTable, nameGenerator, translationOptions, BsonSerializer.DefaultSerializationDomain, data); //TODO It'll be annoying to pass the serialization domain in the call here } #endregion // private fields private readonly TranslationContextData _data; private readonly NameGenerator _nameGenerator; + private readonly IBsonSerializationDomain _serializationDomain; private readonly SymbolTable _symbolTable; private readonly ExpressionTranslationOptions _translationOptions; @@ -46,17 +47,20 @@ private TranslationContext( SymbolTable symbolTable, NameGenerator nameGenerator, ExpressionTranslationOptions translationOptions, + IBsonSerializationDomain serializationDomain, TranslationContextData data = null) { _symbolTable = Ensure.IsNotNull(symbolTable, nameof(symbolTable)); _nameGenerator = Ensure.IsNotNull(nameGenerator, nameof(nameGenerator)); _translationOptions = translationOptions ?? new ExpressionTranslationOptions(); + _serializationDomain = Ensure.IsNotNull(serializationDomain, nameof(serializationDomain)); _data = data; // can be null } // public properties public TranslationContextData Data => _data; public NameGenerator NameGenerator => _nameGenerator; + public IBsonSerializationDomain SerializationDomain => _serializationDomain; public SymbolTable SymbolTable => _symbolTable; public ExpressionTranslationOptions TranslationOptions => _translationOptions;