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 15 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions src/MongoDB.Bson/BsonDefaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static IBsonSerializer DynamicArraySerializer
{
if (!__dynamicArraySerializerWasSet)
{
__dynamicArraySerializer = BsonSerializer.LookupSerializer<List<object>>();
__dynamicArraySerializer = BsonSerializer.LookupSerializer<List<object>>(); //TODO Should we change this? Maybe all the classes that are using this should use the local domain if this is not set
}
return __dynamicArraySerializer;
}
Expand All @@ -62,7 +62,7 @@ public static IBsonSerializer DynamicDocumentSerializer
{
if (!__dynamicDocumentSerializerWasSet)
{
__dynamicDocumentSerializer = BsonSerializer.LookupSerializer<ExpandoObject>();
__dynamicDocumentSerializer = BsonSerializer.LookupSerializer<ExpandoObject>(); //TODO ??
}
return __dynamicDocumentSerializer;
}
Expand Down
77 changes: 73 additions & 4 deletions src/MongoDB.Bson/BsonExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ 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);

/// <summary>
/// //TODO
/// </summary>
/// <param name="obj"></param>
/// <param name="nominalType"></param>
/// <param name="serializationDomain"></param>
/// <param name="writerSettings"></param>
/// <param name="serializer"></param>
/// <param name="configurator"></param>
/// <param name="args"></param>
/// <param name="estimatedBsonSize"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ArgumentNullException"></exception>
public 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 +109,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 +163,28 @@ 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);

/// <summary>
/// //TODO
/// </summary>
/// <param name="obj"></param>
/// <param name="nominalType"></param>
/// <param name="serializationDomain"></param>
/// <param name="serializer"></param>
/// <param name="configurator"></param>
/// <param name="args"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public 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 +211,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 +272,29 @@ 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);

/// <summary>
/// //TODO
/// </summary>
/// <param name="obj"></param>
/// <param name="nominalType"></param>
/// <param name="domain"></param>
/// <param name="writerSettings"></param>
/// <param name="serializer"></param>
/// <param name="configurator"></param>
/// <param name="args"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public 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 +305,7 @@ public static string ToJson(

if (serializer == null)
{
serializer = BsonSerializer.LookupSerializer(nominalType);
serializer = domain.LookupSerializer(nominalType);
}
if (serializer.ValueType != nominalType)
{
Expand Down
3 changes: 2 additions & 1 deletion src/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/MongoDB.Bson/IO/BsonBinaryWriterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ protected override BsonWriterSettings CloneImplementation()
Encoding = _encoding,
FixOldBinarySubTypeOnOutput = _fixOldBinarySubTypeOnOutput,
MaxDocumentSize = _maxDocumentSize,
MaxSerializationDepth = MaxSerializationDepth
MaxSerializationDepth = MaxSerializationDepth,
SerializationDomain = SerializationDomain,
};
return clone;
}
Expand Down
2 changes: 1 addition & 1 deletion src/MongoDB.Bson/IO/BsonDocumentReaderSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static BsonDocumentReaderSettings Defaults
/// <returns>A clone of the settings.</returns>
protected override BsonReaderSettings CloneImplementation()
{
var clone = new BsonDocumentReaderSettings();
var clone = new BsonDocumentReaderSettings { SerializationDomain = SerializationDomain }; //TODO This can be improved
return clone;
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/MongoDB.Bson/IO/BsonReaderSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

using System;
using MongoDB.Bson.Serialization;

namespace MongoDB.Bson.IO
{
Expand All @@ -24,6 +25,7 @@ public abstract class BsonReaderSettings
{
// private fields
private bool _isFrozen;
private IBsonSerializationDomain _serializationDomain;

// constructors
/// <summary>
Expand Down Expand Up @@ -77,6 +79,19 @@ public BsonReaderSettings FrozenCopy()
}
}

/// <summary>
/// //TODO
/// </summary>
public IBsonSerializationDomain SerializationDomain
{
get => _serializationDomain;
set
{
if (_isFrozen) { ThrowFrozenException(); }
_serializationDomain = value;
}
}

// protected methods
/// <summary>
/// Creates a clone of the settings.
Expand Down
15 changes: 15 additions & 0 deletions src/MongoDB.Bson/IO/BsonWriterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

using System;
using MongoDB.Bson.Serialization;

namespace MongoDB.Bson.IO
{
Expand All @@ -25,6 +26,7 @@ public abstract class BsonWriterSettings
// private fields
private bool _isFrozen;
private int _maxSerializationDepth = BsonDefaults.MaxSerializationDepth;
private IBsonSerializationDomain _serializationDomain;

// constructors
/// <summary>
Expand Down Expand Up @@ -92,6 +94,19 @@ public BsonWriterSettings FrozenCopy()
}
}

/// <summary>
/// //TODO
/// </summary>
public IBsonSerializationDomain SerializationDomain
{
get => _serializationDomain;
set
{
if (_isFrozen) { ThrowFrozenException(); }
_serializationDomain = value;
}
}

// protected methods
/// <summary>
/// Creates a clone of the settings.
Expand Down
10 changes: 9 additions & 1 deletion src/MongoDB.Bson/IO/IBsonReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public interface IBsonReader : IDisposable
/// <summary>
/// Pops the settings.
/// </summary>
void PopSettings();
void PopSettings(); //TODO Why do we have push and pop methods? They are not used. We should remove them.

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

//TODO I'm not sure why this was not already present, there is already an equivalent in IBsonWriter.
//We can also avoid adding this to the interface and casting all the occurrences of IBsonReader to BsonReader (the base class for all readers in our codebase).
//Of course this would be a problem if someone implements IBsonReader in a different way.
/// <summary>
/// Gets the settings of the reader.
/// </summary>
BsonReaderSettings Settings { get; }

/// <summary>
/// Skips the name (reader must be positioned on a name).
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/MongoDB.Bson/IO/JsonReaderSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static JsonReaderSettings Defaults
/// <returns>A clone of the settings.</returns>
protected override BsonReaderSettings CloneImplementation()
{
var clone = new JsonReaderSettings();
var clone = new JsonReaderSettings { SerializationDomain = SerializationDomain }; //TODO This can be improved
return clone;
}
}
Expand Down
58 changes: 50 additions & 8 deletions src/MongoDB.Bson/ObjectModel/BsonDocumentWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,19 @@ public object Wrapped
/// <typeparam name="TNominalType">The nominal type of the wrapped object.</typeparam>
/// <param name="value">The wrapped object.</param>
/// <returns>A BsonDocumentWrapper.</returns>
public static BsonDocumentWrapper Create<TNominalType>(TNominalType value)
public static BsonDocumentWrapper Create<TNominalType>(TNominalType value) =>
Create(value, BsonSerializer.DefaultSerializationDomain);

/// <summary>
/// //TODO
/// </summary>
/// <param name="value"></param>
/// <param name="domain"></param>
/// <typeparam name="TNominalType"></typeparam>
/// <returns></returns>
public static BsonDocumentWrapper Create<TNominalType>(TNominalType value, IBsonSerializationDomain domain)
{
return Create(typeof(TNominalType), value);
return Create(typeof(TNominalType), value, domain);
}

/// <summary>
Expand All @@ -102,9 +112,19 @@ public static BsonDocumentWrapper Create<TNominalType>(TNominalType value)
/// <param name="nominalType">The nominal type of the wrapped object.</param>
/// <param name="value">The wrapped object.</param>
/// <returns>A BsonDocumentWrapper.</returns>
public static BsonDocumentWrapper Create(Type nominalType, object value)
public static BsonDocumentWrapper Create(Type nominalType, object value) =>
Create(nominalType, value, BsonSerializer.DefaultSerializationDomain);

/// <summary>
/// //TODO
/// </summary>
/// <param name="nominalType"></param>
/// <param name="value"></param>
/// <param name="domain"></param>
/// <returns></returns>
public static BsonDocumentWrapper Create(Type nominalType, object value, IBsonSerializationDomain domain)
{
var serializer = BsonSerializer.LookupSerializer(nominalType);
var serializer = domain.LookupSerializer(nominalType);
return new BsonDocumentWrapper(value, serializer);
}

Expand All @@ -114,14 +134,25 @@ public static BsonDocumentWrapper Create(Type nominalType, object value)
/// <typeparam name="TNominalType">The nominal type of the wrapped objects.</typeparam>
/// <param name="values">A list of wrapped objects.</param>
/// <returns>A list of BsonDocumentWrappers.</returns>
public static IEnumerable<BsonDocumentWrapper> CreateMultiple<TNominalType>(IEnumerable<TNominalType> values)
public static IEnumerable<BsonDocumentWrapper> CreateMultiple<TNominalType>(IEnumerable<TNominalType> values) =>
CreateMultiple(values, BsonSerializer.DefaultSerializationDomain);

/// <summary>
/// //TODO
/// </summary>
/// <param name="values"></param>
/// <param name="domain"></param>
/// <typeparam name="TNominalType"></typeparam>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static IEnumerable<BsonDocumentWrapper> CreateMultiple<TNominalType>(IEnumerable<TNominalType> values, IBsonSerializationDomain domain)
{
if (values == null)
{
throw new ArgumentNullException("values");
}

var serializer = BsonSerializer.LookupSerializer(typeof(TNominalType));
var serializer = domain.LookupSerializer(typeof(TNominalType));
return values.Select(v => new BsonDocumentWrapper(v, serializer));
}

Expand All @@ -131,7 +162,18 @@ public static IEnumerable<BsonDocumentWrapper> CreateMultiple<TNominalType>(IEnu
/// <param name="nominalType">The nominal type of the wrapped object.</param>
/// <param name="values">A list of wrapped objects.</param>
/// <returns>A list of BsonDocumentWrappers.</returns>
public static IEnumerable<BsonDocumentWrapper> CreateMultiple(Type nominalType, IEnumerable values)
public static IEnumerable<BsonDocumentWrapper> CreateMultiple(Type nominalType, IEnumerable values) =>
CreateMultiple(nominalType, values, BsonSerializer.DefaultSerializationDomain);

/// <summary>
/// //TODO
/// </summary>
/// <param name="nominalType"></param>
/// <param name="values"></param>
/// <param name="domain"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static IEnumerable<BsonDocumentWrapper> CreateMultiple(Type nominalType, IEnumerable values, IBsonSerializationDomain domain)
{
if (nominalType == null)
{
Expand All @@ -142,7 +184,7 @@ public static IEnumerable<BsonDocumentWrapper> CreateMultiple(Type nominalType,
throw new ArgumentNullException("values");
}

var serializer = BsonSerializer.LookupSerializer(nominalType);
var serializer = domain.LookupSerializer(nominalType);
return values.Cast<object>().Select(v => new BsonDocumentWrapper(v, serializer));
}

Expand Down
Loading