Skip to content

CSHARP-3985: Support multiple SerializerRegistries #1592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 51 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
3c99f6d
Rebase commit
papafe May 26, 2025
d087b6c
Corrected type
papafe May 26, 2025
975545a
Various improvements, and added test for discriminators.
papafe May 26, 2025
ecd84a8
Removed comment.
papafe May 26, 2025
a4d92cc
Small corrections.
papafe May 26, 2025
7280ac5
Small correction.
papafe May 26, 2025
27ccb7b
Corrected test
papafe May 26, 2025
e589695
Correction for test
papafe May 26, 2025
5efa4da
Correction
papafe May 26, 2025
962861f
Removed new tests untul refactoring
papafe May 26, 2025
0b92d63
Added domain to MongoQueryProvider
papafe May 27, 2025
6d5fb86
Small fix
papafe May 27, 2025
d1585d1
Corrected freeze
papafe May 27, 2025
5e6931c
Small correction
papafe May 27, 2025
e6b8b35
Fixed BsonClassMap.Freeze and Convention Apply
papafe May 27, 2025
818dc7e
Small fix.
papafe Jun 4, 2025
543c396
Corrected test
papafe Jun 4, 2025
f07be62
Made conventions internal
papafe Jun 4, 2025
f845894
Corrected accessibility
papafe Jun 4, 2025
a3afabb
Fixed discriminator method
papafe Jun 12, 2025
1791906
Simplified
papafe Jun 12, 2025
3a2b361
Hide IBsonReader settings
papafe Jun 12, 2025
fe78c71
Other improvements
papafe Jun 12, 2025
63a8b64
Added constructor to avoid api compat issue
papafe Jun 13, 2025
a641602
Correct
papafe Jun 13, 2025
ef7a962
Small fixes
papafe Jun 13, 2025
b489c38
Various fixes
papafe Jun 13, 2025
cacf077
Added BsonDefaults to domain
papafe Jun 16, 2025
6ccc864
Various fixes to hide API
papafe Jun 16, 2025
4a5220a
Small things
papafe Jun 17, 2025
697784b
Builders example
papafe Jun 17, 2025
97fd948
Removed references to certain parts of BsonDefaults.
papafe Jun 20, 2025
ecf6f92
Various fixes
papafe Jun 20, 2025
7271903
Moved to internal 1
papafe Jun 25, 2025
e513938
More internal
papafe Jun 25, 2025
4c5bdcc
Removed final internal
papafe Jun 25, 2025
714c419
Improvements
papafe Jun 26, 2025
c796201
Small comments
papafe Jun 27, 2025
0f7cc7b
Some comments
papafe Jun 28, 2025
c56f972
Added getDiscriminatorInternal
papafe Jun 28, 2025
83ad951
Merged IBsonSerializationDomainInternal into IBsonSerializationDomain…
papafe Jun 28, 2025
34dce8a
Missing piece.
papafe Jun 28, 2025
7311b35
Fix for getDicriminatorConvention and IBsonIdProvider
papafe Jun 28, 2025
e9511c0
Big serializer check
papafe Jun 30, 2025
a783914
Fix for testing
papafe Jun 30, 2025
4c7d7ac
Added comment
papafe Jun 30, 2025
ee4410a
Small fix
papafe Jun 30, 2025
a31265a
Various fixes about RenderArgs plus new tests
papafe Jul 1, 2025
ef6d8bd
Small fix
papafe Jul 1, 2025
e7a703e
Simplified tests
papafe Jul 1, 2025
b86494b
Small fixes
papafe Jul 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 13 additions & 38 deletions src/MongoDB.Bson/BsonDefaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,71 +24,46 @@ namespace MongoDB.Bson
/// </summary>
public static class BsonDefaults
{
// private static fields
private static bool __dynamicArraySerializerWasSet;
private static IBsonSerializer __dynamicArraySerializer;
private static bool __dynamicDocumentSerializerWasSet;
private static IBsonSerializer __dynamicDocumentSerializer;
private static int __maxDocumentSize = int.MaxValue;
private static int __maxSerializationDepth = 100;

// public static properties
/// <summary>
/// Gets or sets the dynamic array serializer.
/// </summary>
public static IBsonSerializer DynamicArraySerializer
{
get
{
if (!__dynamicArraySerializerWasSet)
{
__dynamicArraySerializer = BsonSerializer.LookupSerializer<List<object>>();
}
return __dynamicArraySerializer;
}
set
{
__dynamicArraySerializerWasSet = true;
__dynamicArraySerializer = value;
}
get => BsonSerializer.DefaultSerializationDomain.BsonDefaults.DynamicArraySerializer;
set => BsonSerializer.DefaultSerializationDomain.BsonDefaults.DynamicArraySerializer = value;
}

/// <summary>
/// Gets or sets the dynamic document serializer.
/// </summary>
public static IBsonSerializer DynamicDocumentSerializer
{
get
{
if (!__dynamicDocumentSerializerWasSet)
{
__dynamicDocumentSerializer = BsonSerializer.LookupSerializer<ExpandoObject>();
}
return __dynamicDocumentSerializer;
}
set
{
__dynamicDocumentSerializerWasSet = true;
__dynamicDocumentSerializer = value;
}
get => BsonSerializer.DefaultSerializationDomain.BsonDefaults.DynamicDocumentSerializer;
set => BsonSerializer.DefaultSerializationDomain.BsonDefaults.DynamicDocumentSerializer = value;
}

/* DOMAIN-API We should modify the API to have those two values (and in the writer/reader settings where they are used) be nullable.
* The problem is that we need to now when these values have been set externally or not. If they have not, then they should
* be retrieved from the closest domain.
*/

/// <summary>
/// Gets or sets the default max document size. The default is 4MiB.
/// </summary>
public static int MaxDocumentSize
{
get { return __maxDocumentSize; }
set { __maxDocumentSize = value; }
get => BsonSerializer.DefaultSerializationDomain.BsonDefaults.MaxDocumentSize;
set => BsonSerializer.DefaultSerializationDomain.BsonDefaults.MaxDocumentSize = value;
}

/// <summary>
/// Gets or sets the default max serialization depth (used to detect circular references during serialization). The default is 100.
/// </summary>
public static int MaxSerializationDepth
{
get { return __maxSerializationDepth; }
set { __maxSerializationDepth = value; }
get => BsonSerializer.DefaultSerializationDomain.BsonDefaults.MaxSerializationDepth;
set => BsonSerializer.DefaultSerializationDomain.BsonDefaults.MaxSerializationDepth = value;
}
}
}
73 changes: 73 additions & 0 deletions src/MongoDB.Bson/BsonDefaultsDomain.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* 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.Collections.Generic;
using System.Dynamic;
using MongoDB.Bson.Serialization;

namespace MongoDB.Bson
{
internal class BsonDefaultsDomain : IBsonDefaults
{
private IBsonSerializationDomain _serializationDomain;
private bool _dynamicArraySerializerWasSet;
private IBsonSerializer _dynamicArraySerializer;
private bool _dynamicDocumentSerializerWasSet;
private IBsonSerializer _dynamicDocumentSerializer;

public BsonDefaultsDomain(IBsonSerializationDomain serializationDomain)
{
_serializationDomain = serializationDomain;
}

public IBsonSerializer DynamicArraySerializer
{
get
{
if (!_dynamicArraySerializerWasSet)
{
_dynamicArraySerializer = _serializationDomain.LookupSerializer<List<object>>();
}
return _dynamicArraySerializer;
}
set
{
_dynamicArraySerializerWasSet = true;
_dynamicArraySerializer = value;
}
}

public IBsonSerializer DynamicDocumentSerializer
{
get
{
if (!_dynamicDocumentSerializerWasSet)
{
_dynamicDocumentSerializer = _serializationDomain.LookupSerializer<ExpandoObject>();
}
return _dynamicDocumentSerializer;
}
set
{
_dynamicDocumentSerializerWasSet = true;
_dynamicDocumentSerializer = value;
}
}

public int MaxDocumentSize { get; set; } = int.MaxValue;

public int MaxSerializationDepth { get; set; } = 100;
}
}
55 changes: 51 additions & 4 deletions src/MongoDB.Bson/BsonExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ namespace MongoDB.Bson
/// </summary>
public static class BsonExtensionMethods
{
//DOMAIN-API We should remove this and use the version with the domain.
//QUESTION: Do we want to do something now about this...? It's used also internally, but it seems in most cases it's used for "default serialization", so it should be ok.
/// <summary>
/// Serializes an object to a BSON byte array.
/// </summary>
Expand All @@ -49,6 +51,21 @@ public static byte[] ToBson<TNominalType>(
return ToBson(obj, typeof(TNominalType), writerSettings, serializer, configurator, args, estimatedBsonSize);
}

internal static byte[] ToBson<TNominalType>(
this TNominalType obj,
IBsonSerializationDomain serializationDomain,
IBsonSerializer<TNominalType> serializer = null,
BsonBinaryWriterSettings writerSettings = null,
Action<BsonSerializationContext.Builder> configurator = null,
BsonSerializationArgs args = default(BsonSerializationArgs),
int estimatedBsonSize = 0)
{
args.SetOrValidateNominalType(typeof(TNominalType), "<TNominalType>");

return ToBson(obj, typeof(TNominalType), serializationDomain, writerSettings, serializer, configurator, args, estimatedBsonSize);
}

//DOMAIN-API We should remove this and use the version with the domain.
/// <summary>
/// Serializes an object to a BSON byte array.
/// </summary>
Expand All @@ -68,6 +85,17 @@ public static byte[] ToBson(
BsonBinaryWriterSettings writerSettings = null,
IBsonSerializer serializer = null,
Action<BsonSerializationContext.Builder> configurator = null,
BsonSerializationArgs args = default,
int estimatedBsonSize = 0) => ToBson(obj, nominalType, BsonSerializer.DefaultSerializationDomain, writerSettings,
serializer, configurator, args, estimatedBsonSize);

internal static byte[] ToBson(
this object obj,
Type nominalType,
IBsonSerializationDomain serializationDomain,
BsonBinaryWriterSettings writerSettings = null,
IBsonSerializer serializer = null,
Action<BsonSerializationContext.Builder> configurator = null,
BsonSerializationArgs args = default(BsonSerializationArgs),
int estimatedBsonSize = 0)
{
Expand All @@ -84,7 +112,7 @@ public static byte[] ToBson(

if (serializer == null)
{
serializer = BsonSerializer.LookupSerializer(nominalType);
serializer = serializationDomain.LookupSerializer(nominalType);
}
if (serializer.ValueType != nominalType)
{
Expand Down Expand Up @@ -138,7 +166,16 @@ public static BsonDocument ToBsonDocument(
Type nominalType,
IBsonSerializer serializer = null,
Action<BsonSerializationContext.Builder> configurator = null,
BsonSerializationArgs args = default(BsonSerializationArgs))
BsonSerializationArgs args = default) => ToBsonDocument(obj, nominalType,
BsonSerializer.DefaultSerializationDomain, serializer, configurator, args);

internal static BsonDocument ToBsonDocument(
this object obj,
Type nominalType,
IBsonSerializationDomain serializationDomain,
IBsonSerializer serializer = null,
Action<BsonSerializationContext.Builder> configurator = null,
BsonSerializationArgs args = default)
{
if (nominalType == null)
{
Expand All @@ -165,7 +202,7 @@ public static BsonDocument ToBsonDocument(
return convertibleToBsonDocument.ToBsonDocument(); // use the provided ToBsonDocument method
}

serializer = BsonSerializer.LookupSerializer(nominalType);
serializer = serializationDomain.LookupSerializer(nominalType);
}
if (serializer.ValueType != nominalType)
{
Expand Down Expand Up @@ -226,6 +263,16 @@ public static string ToJson(
JsonWriterSettings writerSettings = null,
IBsonSerializer serializer = null,
Action<BsonSerializationContext.Builder> configurator = null,
BsonSerializationArgs args = default)
=> ToJson(obj, nominalType, BsonSerializer.DefaultSerializationDomain, writerSettings, serializer, configurator, args);

internal static string ToJson(
this object obj,
Type nominalType,
IBsonSerializationDomain domain,
JsonWriterSettings writerSettings = null,
IBsonSerializer serializer = null,
Action<BsonSerializationContext.Builder> configurator = null,
BsonSerializationArgs args = default(BsonSerializationArgs))
{
if (nominalType == null)
Expand All @@ -236,7 +283,7 @@ public static string ToJson(

if (serializer == null)
{
serializer = BsonSerializer.LookupSerializer(nominalType);
serializer = domain.LookupSerializer(nominalType);
}
if (serializer.ValueType != nominalType)
{
Expand Down
88 changes: 88 additions & 0 deletions src/MongoDB.Bson/Builders/BuilderInterfaces.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/* 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 MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;

namespace MongoDB.Bson.Builders;

/* All the builders here contain the methods from the respective domain/classes that can be used for configurations.
*/

internal interface ISerializationDomainBuilder
{
ISerializationDomainBuilder RegisterDiscriminator(Type type, BsonValue discriminator);

ISerializationDomainBuilder RegisterDiscriminatorConvention(Type type, IDiscriminatorConvention convention);

ISerializationDomainBuilder RegisterGenericSerializerDefinition(
Type genericTypeDefinition,
Type genericSerializerDefinition);

ISerializationDomainBuilder RegisterIdGenerator(Type type, IIdGenerator idGenerator);

ISerializationDomainBuilder RegisterSerializationProvider(IBsonSerializationProvider provider);

ISerializationDomainBuilder RegisterSerializer<T>(IBsonSerializer<T> serializer);

ISerializationDomainBuilder RegisterSerializer(Type type, IBsonSerializer serializer);

ISerializationDomainBuilder TryRegisterSerializer(Type type, IBsonSerializer serializer);

ISerializationDomainBuilder TryRegisterSerializer<T>(IBsonSerializer<T> serializer);

ISerializationDomainBuilder UseNullIdChecker(bool useNullIdChecker);

ISerializationDomainBuilder UseZeroIdChecker(bool useZeroIdChecker);

ISerializationDomainBuilder ConfigureClassMap(Action<IBsonClassMapDomainBuilder> configure);

ISerializationDomainBuilder ConfigureConventionRegistry(Action<IConventionRegistryDomainBuilder> configure);

ISerializationDomainBuilder ConfigureBsonDefaults(Action<IBsonDefaultsBuilder> configure);

IBsonSerializationDomain1 Build();
}

internal interface IBsonClassMapDomainBuilder
{
IBsonClassMapDomainBuilder RegisterClassMap<TClass>();

IBsonClassMapDomainBuilder RegisterClassMap<TClass>(Action<BsonClassMap<TClass>> classMapInitializer);

IBsonClassMapDomainBuilder RegisterClassMap(BsonClassMap classMap);

IBsonClassMapDomainBuilder TryRegisterClassMap<TClass>();

IBsonClassMapDomainBuilder TryRegisterClassMap<TClass>(BsonClassMap<TClass> classMap);

IBsonClassMapDomainBuilder TryRegisterClassMap<TClass>(Action<BsonClassMap<TClass>> classMapInitializer);

IBsonClassMapDomainBuilder TryRegisterClassMap<TClass>(Func<BsonClassMap<TClass>> classMapFactory);
}

internal interface IConventionRegistryDomainBuilder
{
IConventionRegistryDomainBuilder Register(string name, IConventionPack conventions, Func<Type, bool> filter);
}

internal interface IBsonDefaultsBuilder
{
IBsonDefaultsBuilder SetDynamicArraySerializer(IBsonSerializer serializer);
IBsonDefaultsBuilder SetDynamicDocumentSerializer(IBsonSerializer serializer);
IBsonDefaultsBuilder SetMaxDocumentSize(int size);
IBsonDefaultsBuilder SetMaxSerializationDepth(int depth);
}
Loading
Loading