diff --git a/src/Primitively.MongoDB.Bson/DependencyInjection.cs b/src/Primitively.MongoDB.Bson/DependencyInjection.cs index 067716f..8f20ef6 100644 --- a/src/Primitively.MongoDB.Bson/DependencyInjection.cs +++ b/src/Primitively.MongoDB.Bson/DependencyInjection.cs @@ -1,5 +1,4 @@ using Primitively.Configuration; -using Primitively.MongoDB.Bson.Serialization; using Primitively.MongoDB.Bson.Serialization.Options; namespace Primitively.MongoDB.Bson; @@ -16,30 +15,9 @@ public static class DependencyInjection /// Configurator /// BsonOptions /// Configurator - public static PrimitivelyConfigurator AddBson(this PrimitivelyConfigurator configurator, BsonOptions? options = null) + public static PrimitivelyConfigurator AddBson(this PrimitivelyConfigurator configurator, Action? options = null) { - return configurator.AddBson(configure => { }, options ?? new BsonOptions()); - } - - /// - /// Register MongoDB nullable and non-nullable Bson serializers - /// - /// Configurator - /// BsonOptions - /// BsonSerializerBuilder - /// Configurator - public static PrimitivelyConfigurator AddBson(this PrimitivelyConfigurator configurator, Action configure, BsonOptions? options = null) - { - BsonSerializerBuilder builder = new(options ??= new BsonOptions()); - builder.SetDefaultGuidRepresentation(); - - if (options.RegisterSerializersForEachTypeInRegistry) - { - builder.RegisterSerializers(register => - register.AddSerializerForEachTypeIn(configurator.Options.Registry)); - } - - configure.Invoke(builder); + options?.Invoke(new BsonOptions()); return configurator; } diff --git a/src/Primitively.MongoDB.Bson/Primitively.MongoDB.Bson.csproj b/src/Primitively.MongoDB.Bson/Primitively.MongoDB.Bson.csproj index 0ae6255..afbe550 100644 --- a/src/Primitively.MongoDB.Bson/Primitively.MongoDB.Bson.csproj +++ b/src/Primitively.MongoDB.Bson/Primitively.MongoDB.Bson.csproj @@ -6,7 +6,7 @@ enable A library which provides MongoDB support for types produced by the Primitively C# source generator true - $(NoWarn);CA1510 + $(NoWarn);CA1510;CS0618 diff --git a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerBuilder.cs b/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerBuilder.cs index 4226bb0..efc83f9 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerBuilder.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerBuilder.cs @@ -1,7 +1,4 @@ -using MongoDB.Bson.Serialization.Serializers; -using MongoDB.Bson.Serialization; -using MongoDB.Bson; -using Primitively.MongoDB.Bson.Serialization.Options; +using Primitively.MongoDB.Bson.Serialization.Options; namespace Primitively.MongoDB.Bson.Serialization; @@ -10,7 +7,6 @@ namespace Primitively.MongoDB.Bson.Serialization; /// public class BsonSerializerBuilder { - private readonly BsonSerializerCacheBuilder _cacheBuilder = new(); private readonly BsonSerializerRegisterBuilder _registerBuilder = new(); private readonly BsonOptions _options; @@ -22,39 +18,6 @@ internal BsonSerializerBuilder(BsonOptions options) _options = options; } - internal BsonSerializerBuilder SetDefaultGuidRepresentation() - { - //var options = _options.GuidOptions; - //var guidSerializer = options.Representation == BsonType.String - // ? new GuidSerializer(BsonType.String) - // : new GuidSerializer(options.GuidRepresentation); - -#pragma warning disable CS0618 // Type or member is obsolete - //BsonDefaults.GuidRepresentation = options.GuidRepresentation; - //BsonDefaults.GuidRepresentationMode = options.GuidRepresentationMode; -#pragma warning restore CS0618 // Type or member is obsolete - - //BsonSerializer.TryRegisterSerializer(typeof(Guid), guidSerializer); - - return this; - } - - /// - /// Override any of the default Primitively serializers with custom ones - /// - /// Cache builder. See - /// The current instance - /// - /// There is a default serializer for each Primitively . These are held in cache. - /// This method allows the default serializer to be replaced with a custom implementation. - /// - public BsonSerializerBuilder DefaultSerializers(Action cache) - { - cache.Invoke(_cacheBuilder); - - return this; - } - /// /// Registers non-nullable and nullable serializer instances for each of the given Primitively types. /// @@ -64,7 +27,6 @@ public BsonSerializerBuilder DefaultSerializers(Action has a matching serializer held in cache. The defaults can be changed using - /// the method. /// public BsonSerializerBuilder RegisterSerializers(Action register) { diff --git a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerCache.cs b/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerCache.cs deleted file mode 100644 index 05ef37d..0000000 --- a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerCache.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Primitively.MongoDB.Bson.Serialization.Serializers; - -namespace Primitively.MongoDB.Bson.Serialization; - -/// -/// A cache of the default serializer classes -/// -internal static class BsonSerializerCache -{ - private static readonly Dictionary _items = new() - { - { DataType.Byte, typeof(BsonIByteSerializer<>) }, - { DataType.DateOnly, typeof(BsonIDateOnlySerializer<>) }, - { DataType.Guid, typeof(BsonIGuidSerializer<>) }, - { DataType.Int, typeof(BsonIIntSerializer<>) }, - { DataType.Long, typeof(BsonILongSerializer<>) }, - { DataType.SByte, typeof(BsonISByteSerializer<>) }, - { DataType.Short, typeof(BsonIShortSerializer<>) }, - { DataType.String, typeof(BsonIStringSerializer<>) }, - { DataType.UInt, typeof(BsonIUIntSerializer<>) }, - { DataType.ULong, typeof(BsonIULongSerializer<>) }, - { DataType.UShort, typeof(BsonIUShortSerializer<>) } - }; - - public static Type Get(DataType dataType) => _items[dataType]; - - public static void Set(DataType dataType, Type serializerType) - { - if (!serializerType.IsGenericTypeDefinition) - { - throw new ArgumentException("The serializer type must be a generic type definition e.g. StringBsonSerializer<>", nameof(serializerType)); - } - - var parameters = serializerType.GetGenericArguments(); - if (parameters.Length > 1) - { - throw new ArgumentException("The serializer type should only have one generic type parameter", nameof(serializerType)); - } - - var parameter = parameters[0]; - var interfaces = parameter.GetInterfaces().ToList(); - var isValidImplementation = interfaces.Exists(w => w == dataType switch - { - DataType.Byte => typeof(IByte), - DataType.DateOnly => typeof(IDateOnly), - DataType.Guid => typeof(IGuid), - DataType.Int => typeof(IInt), - DataType.Long => typeof(ILong), - DataType.SByte => typeof(ISByte), - DataType.Short => typeof(IShort), - DataType.String => typeof(IString), - DataType.UInt => typeof(IUInt), - DataType.ULong => typeof(IULong), - DataType.UShort => typeof(IUShort), - _ => throw new NotImplementedException(), - }); - - if (!isValidImplementation) - { - throw new ArgumentException("The serializer type does not implement the expected Primitively type interface for the given data type " + - "e.g. DataType.Byte should have a serializer type that has generic type constrained to IByte", nameof(serializerType)); - } - - _items[dataType] = serializerType; - } -} diff --git a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerCacheBuilder.cs b/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerCacheBuilder.cs deleted file mode 100644 index cf2150d..0000000 --- a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerCacheBuilder.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Primitively.MongoDB.Bson.Serialization; - -/// -/// Fluent builder class to replace the default Primitively serializers with custom implementations -/// -public class BsonSerializerCacheBuilder -{ - internal BsonSerializerCacheBuilder() { } - - /// - /// Replace the default Primitively Bson Serializer with a custom one. - /// - /// - /// - /// BsonSerializerBuilder - public BsonSerializerCacheBuilder SetSerializer(DataType dataType, Type serializerType) - { - BsonSerializerCache.Set(dataType, serializerType); - - return this; - } -} diff --git a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerRegisterBuilder.cs b/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerRegisterBuilder.cs index 98b0146..8fc802d 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerRegisterBuilder.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/BsonSerializerRegisterBuilder.cs @@ -1,6 +1,8 @@ -using MongoDB.Bson.Serialization; +using System.Collections.Concurrent; +using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; using Primitively.Configuration; +using Primitively.MongoDB.Bson.Serialization.Options; namespace Primitively.MongoDB.Bson.Serialization; @@ -9,146 +11,174 @@ namespace Primitively.MongoDB.Bson.Serialization; /// public class BsonSerializerRegisterBuilder { - private static readonly List _primitiveTypes = new(); + private static readonly ConcurrentBag _primitiveTypes = new(); internal BsonSerializerRegisterBuilder() { } /// - /// Automatically register a nullable and a non-nullable Bson serializer for the provided Primitively type + /// Register nullable and non-nullable Bson serializers for all the Primitively types contained + /// in the source generated repository /// - /// IPrimitive + /// IPrimitiveRepository /// BsonSerializerRegisterBuilder /// - /// The type of serializer used is governed by the BsonSerializerOptions. If a serializer for the given type - /// is already registered, subsequent attempts for the same type will be ignored. + /// The type of serializer used is governed by the BsonSerializerOptions. + /// If a serializer for the given type is already registered, subsequent attempts for the same type will be ignored. + /// To use a custom serializer for one or more types in a repository. Simply register them individually + /// first before calling this method. /// - public BsonSerializerRegisterBuilder AddSerializerForType() where TPrimitive : struct, IPrimitive + public BsonSerializerRegisterBuilder ForEachTypeIn() where TPrimitiveRepository : class, IPrimitiveRepository, new() { - // Get a default instance of the provided Primitively struct type - var primitive = new TPrimitive(); + // Get a list of the source generated Primitively types + var repository = new TPrimitiveRepository(); - // Generate a nullable and non-nullable Bson serializer for the Primitively struct - var serializerType = BsonSerializerCache.Get(primitive.DataType); + return ForEachTypeIn(repository); + } - RegisterBsonSerializer(typeof(TPrimitive), serializerType); + public BsonSerializerRegisterBuilder ForEachTypeIn(IPrimitiveRepository repository) + { + // Get a list of the source generated Primitively types + var primitives = repository.GetTypes(); + + if (primitives.Count == 0) + { + return this; + } + + RegisterBsonSerializers(primitives); return this; } /// - /// Register a nullable and a non-nullable Bson serializer for the provided Primitively type + /// Automatically register a nullable and a non-nullable Bson serializer for the provided Primitively type /// /// IPrimitive - /// IBsonSerializer /// BsonSerializerRegisterBuilder - /// - /// The type of serializer used is governed by the TBsonSerializer type parameter. This allows for - /// individual primitive types to have their own serialiser, rather than the one defined in BsonSerializerOptions. - /// If a serializer for the given type is already registered, subsequent attempts for the same type will be ignored. - /// - public BsonSerializerRegisterBuilder AddSerializerForType() - where TPrimitive : struct, IPrimitive - where TBsonSerializer : class, IBsonSerializer + public BsonSerializerRegisterBuilder ForType() where TPrimitive : struct, IPrimitive { - RegisterBsonSerializer(typeof(TPrimitive), typeof(TBsonSerializer)); + // Get a default instance of the provided Primitively type to obtain the DataType enum property value + var primitive = new TPrimitive(); + var dataType = primitive.DataType; + + RegisterBsonSerializer(typeof(TPrimitive), dataType); return this; } /// - /// Register nullable and non-nullable Bson serializers for each of the Primitively types in the registry + /// Automatically register a nullable and a non-nullable Bson serializer for the provided Primitively type /// - /// PrimitiveRegistry + /// IPrimitive /// BsonSerializerRegisterBuilder - public BsonSerializerRegisterBuilder AddSerializerForEachTypeIn(PrimitiveRegistry registry) + public BsonSerializerRegisterBuilder ForType(IBsonSerializer serializerInstance) where TPrimitive : struct, IPrimitive { - if (registry.IsEmpty) + // Check that Primitive types has not been handled already + var primitiveType = typeof(TPrimitive); + + // Check that Primitive types has not been handled already + if (!_primitiveTypes.Contains(primitiveType)) { - return this; + // Add the type to a collection to provide a data source for the above check + _primitiveTypes.Add(primitiveType); + + // Register a Serializer for the Primitively type + BsonSerializer.TryRegisterSerializer(primitiveType, serializerInstance); } - foreach (var primitiveInfo in registry.ToList()) + // Construct a nullable version of the Primitively type + var nullablePrimitiveType = typeof(Nullable<>).MakeGenericType(primitiveType); + + // Check that nullable Primitive types has not been handled already + if (!_primitiveTypes.Contains(nullablePrimitiveType)) { - AddSerializerForType(primitiveInfo); + // Add the type to a collection to provide a data source for the above check + _primitiveTypes.Add(nullablePrimitiveType); + + // Register a NullableSerializer for a nullable version of the Primitively type + BsonSerializer.TryRegisterSerializer(nullablePrimitiveType, serializerInstance); } return this; } /// - /// Register nullable and non-nullable Bson serializers for all the Primitively types contained - /// in the source generated repository + /// Register a nullable and a non-nullable Bson serializer for the provided Primitively type /// - /// IPrimitiveRepository + /// IPrimitive + /// IBsonSerializer /// BsonSerializerRegisterBuilder /// - /// The type of serializer used is governed by the BsonSerializerOptions. + /// The type of serializer used is governed by the TBsonSerializer type parameter. This allows for + /// individual primitive types to have their own serialiser, rather than the one defined in BsonSerializerOptions. /// If a serializer for the given type is already registered, subsequent attempts for the same type will be ignored. - /// To use a custom serializer for one or more types in a repository. Simply register them individually - /// first before calling this method. /// - public BsonSerializerRegisterBuilder AddSerializerForEachTypeIn() - where TPrimitiveRepository : class, IPrimitiveRepository, new() + public BsonSerializerRegisterBuilder ForType() + where TPrimitive : struct, IPrimitive + where TBsonSerializer : class, IBsonSerializer, new() { - // Get a list of the source generated Primitively types - var primitiveRepository = new TPrimitiveRepository(); + // Create an instance of the serializer + var serializerInstance = (TBsonSerializer)Activator.CreateInstance(typeof(TBsonSerializer))!; - foreach (var primitiveInfo in primitiveRepository.GetTypes()) - { - var serializerType = BsonSerializerCache.Get(primitiveInfo.DataType); + return ForType(serializerInstance); + } - RegisterBsonSerializer(primitiveInfo.Type, serializerType); + /// + /// Register nullable and non-nullable Bson serializers for each of the Primitively types in the registry + /// + /// PrimitiveRegistry + /// BsonSerializerRegisterBuilder + internal BsonSerializerRegisterBuilder ForEachTypeIn(PrimitiveRegistry registry) + { + if (registry.IsEmpty) + { + return this; } + RegisterBsonSerializers(registry.ToList()); + return this; } - private static void RegisterBsonSerializer(Type primitiveType, Type serializerType) + private static void RegisterBsonSerializer(Type primitiveType, DataType dataType) { // Check that Primitive types has not been handled already - if (_primitiveTypes.Contains(primitiveType)) + if (!_primitiveTypes.Contains(primitiveType)) { - return; - } - - // Add the type to a collection to provide a data source for the above check - _primitiveTypes.Add(primitiveType); - - // Construct a Primitively serializer of the Primitively type - var primitiveSerializerType = serializerType.IsGenericTypeDefinition ? serializerType.MakeGenericType(primitiveType) : serializerType; + // Add the type to a collection to provide a data source for the above check + _primitiveTypes.Add(primitiveType); - // Create a Primitively serializer instance - var primitiveSerializerInstance = (IBsonSerializer)Activator.CreateInstance(primitiveSerializerType)!; + // Create a Primitively serializer instance + var serializerType = BsonSerializerOptionsCache.Get(dataType); // TODO: Update Get method/call to ensure failure handled + var serializerInstance = serializerType.CreateInstance(primitiveType); - // Register a Serializer for the Primitively type - BsonSerializer.TryRegisterSerializer(primitiveType, primitiveSerializerInstance); + // Register a Serializer for the Primitively type + BsonSerializer.TryRegisterSerializer(primitiveType, serializerInstance); + } // Construct a nullable version of the Primitively type var nullablePrimitiveType = typeof(Nullable<>).MakeGenericType(primitiveType); - // Create a Nullable Primitively serializer instance - var nullablePrimitiveSerializerInstance = NullableSerializer.Create(primitiveSerializerInstance); + // Check that nullable Primitive types has not been handled already + if (!_primitiveTypes.Contains(nullablePrimitiveType)) + { + // Add the type to a collection to provide a data source for the above check + _primitiveTypes.Add(nullablePrimitiveType); + + // Create a nullable Primitively serializer instance + var serializerType = BsonSerializerOptionsCache.Get(dataType); // TODO: Update Get method/call to ensure failure handled + var serializerInstance = NullableSerializer.Create(serializerType.CreateInstance(primitiveType)); - // Register a NullableSerializer for a nullable version of the Primitively type - BsonSerializer.TryRegisterSerializer(nullablePrimitiveType, nullablePrimitiveSerializerInstance); + // Register a NullableSerializer for a nullable version of the Primitively type + BsonSerializer.TryRegisterSerializer(nullablePrimitiveType, serializerInstance); + } } - /// - /// Automatically register a nullable and a non-nullable Bson serializer for the provided Primitively type - /// - /// PrimitiveInfo - /// BsonSerializerRegisterBuilder - /// - /// The type of serializer used is governed by the BsonSerializerOptions. If a serializer for the given type - /// is already registered, subsequent attempts for the same type will be ignored. - /// - private BsonSerializerRegisterBuilder AddSerializerForType(PrimitiveInfo primitiveInfo) + private static void RegisterBsonSerializers(IEnumerable primitives) { - // Generate a nullable and non-nullable Bson serializer for the Primitively struct - var serializerType = BsonSerializerCache.Get(primitiveInfo.DataType); - - RegisterBsonSerializer(primitiveInfo.Type, serializerType); - - return this; + foreach (var primitiveInfo in primitives) + { + RegisterBsonSerializer(primitiveInfo.Type, primitiveInfo.DataType); + } } } diff --git a/src/Primitively.MongoDB.Bson/Serialization/IGuidRepresentationConfigurable.cs b/src/Primitively.MongoDB.Bson/Serialization/IGuidRepresentationConfigurable.cs index 8ee131b..ecfd442 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/IGuidRepresentationConfigurable.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/IGuidRepresentationConfigurable.cs @@ -15,3 +15,17 @@ public interface IGuidRepresentationConfigurable : IHasGuidRepresentationSeriali /// The reconfigured serializer. IBsonSerializer WithGuidRepresentation(GuidRepresentation representation); } + +/// +/// Represents a serializer that has a GuidRepresentation property. +/// +/// The type of the serializer. +public interface IGuidRepresentationConfigurable : IGuidRepresentationConfigurable where TSerializer : IBsonSerializer +{ + /// + /// Returns a serializer that has been reconfigured with the specified GUID representation. + /// + /// The GUID representation. + /// The reconfigured serializer. + new TSerializer WithGuidRepresentation(GuidRepresentation representation); +} diff --git a/src/Primitively.MongoDB.Bson/Serialization/IGuidRepresentationConfigurable`1.cs b/src/Primitively.MongoDB.Bson/Serialization/IGuidRepresentationConfigurable`1.cs deleted file mode 100644 index c515846..0000000 --- a/src/Primitively.MongoDB.Bson/Serialization/IGuidRepresentationConfigurable`1.cs +++ /dev/null @@ -1,18 +0,0 @@ -using MongoDB.Bson; -using MongoDB.Bson.Serialization; - -namespace Primitively.MongoDB.Bson.Serialization; - -/// -/// Represents a serializer that has a GuidRepresentation property. -/// -/// The type of the serializer. -public interface IGuidRepresentationConfigurable : IGuidRepresentationConfigurable where TSerializer : IBsonSerializer -{ - /// - /// Returns a serializer that has been reconfigured with the specified GUID representation. - /// - /// The GUID representation. - /// The reconfigured serializer. - new TSerializer WithGuidRepresentation(GuidRepresentation representation); -} diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIByteSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIByteSerializerOptions.cs index 5cdb33c..d73c391 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIByteSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIByteSerializerOptions.cs @@ -4,30 +4,21 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIByteSerializerOptions : IBsonSerializerOptions +public record BsonIByteSerializerOptions : IBsonSerializerOptions { public DataType DataType { get; } = DataType.Byte; public BsonType Representation { get; set; } = BsonType.Int32; public Type SerializerType { get; set; } = typeof(BsonIByteSerializer<>); - //Func CreateInstance { get; set; } = (options, primitiveType) => - //{ - // // Construct a Primitively serializer of the Primitively type - // var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - - // // Create a Primitively serializer instance - // var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, options.Representation)!; - - // return serializerInstance; - //}; - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance - var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, Representation)!; + // Create an instance of the serializer + var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, options.Representation)!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIDateOnlySerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIDateOnlySerializerOptions.cs index ffdb7d2..8152d58 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIDateOnlySerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIDateOnlySerializerOptions.cs @@ -4,20 +4,21 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIDateOnlySerializerOptions : IBsonSerializerOptions +public record BsonIDateOnlySerializerOptions : IBsonSerializerOptions { public DataType DataType { get; } = DataType.DateOnly; public BsonType Representation { get; set; } = BsonType.DateTime; public Type SerializerType { get; set; } = typeof(BsonIDateOnlySerializer<>); - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance - var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, Representation)!; + // Create an instance of the serializer + var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, options.Representation)!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIGuidSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIGuidSerializerOptions.cs index 8598b58..1ddd075 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIGuidSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIGuidSerializerOptions.cs @@ -4,23 +4,31 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIGuidSerializerOptions : IBsonSerializerOptions +public record BsonIGuidSerializerOptions : IBsonIGuidSerializerOptions { public DataType DataType { get; } = DataType.Guid; public BsonType Representation { get; set; } = BsonType.Binary; - public GuidRepresentation GuidRepresentation { get; set; } = GuidRepresentation.CSharpLegacy; - public GuidRepresentationMode GuidRepresentationMode { get; set; } = GuidRepresentationMode.V2; + public GuidRepresentation GuidRepresentation { get; set; } = BsonDefaults.GuidRepresentation; public Type SerializerType { get; set; } = typeof(BsonIGuidSerializer<>); - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Check that the application is using the correct GuidRepresentationMode + if (options.GuidRepresentation != BsonDefaults.GuidRepresentation && BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2) + { + // V3 mode permits a mixture of searchable GUID representations to exist side by side + // TODO: Consider throwing an exception instead rather than forcing the mode to V3 + BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3; + } + + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance - object argument = Representation == BsonType.String ? Representation : GuidRepresentation; + // Create an instance of the serializer + object argument = options.Representation == BsonType.String ? BsonType.String : options.GuidRepresentation; var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, argument)!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIIntSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIIntSerializerOptions.cs index 46f2fd8..082b55b 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIIntSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIIntSerializerOptions.cs @@ -5,25 +5,26 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIIntSerializerOptions : IBsonSerializerOptions, IRepresentationConverterOptions +public record BsonIIntSerializerOptions : IBsonConvertibleSerializerOptions { public DataType DataType { get; } = DataType.Int; public BsonType Representation { get; set; } = BsonType.Int32; public Type SerializerType { get; set; } = typeof(BsonIIntSerializer<>); public bool AllowOverflow { get; set; } public bool AllowTruncation { get; set; } - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance + // Create an instance of the serializer var serializerInstance = (IBsonSerializer)Activator.CreateInstance( serializerType, - Representation, - new RepresentationConverter(AllowOverflow, AllowTruncation))!; + options.Representation, + new RepresentationConverter(options.AllowOverflow, options.AllowTruncation))!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonILongSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonILongSerializerOptions.cs index f3632d3..b589742 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonILongSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonILongSerializerOptions.cs @@ -5,25 +5,26 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonILongSerializerOptions : IBsonSerializerOptions, IRepresentationConverterOptions +public record BsonILongSerializerOptions : IBsonConvertibleSerializerOptions { public DataType DataType { get; } = DataType.Long; public BsonType Representation { get; set; } = BsonType.Int64; public Type SerializerType { get; set; } = typeof(BsonILongSerializer<>); public bool AllowOverflow { get; set; } public bool AllowTruncation { get; set; } - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance + // Create an instance of the serializer var serializerInstance = (IBsonSerializer)Activator.CreateInstance( serializerType, - Representation, - new RepresentationConverter(AllowOverflow, AllowTruncation))!; + options.Representation, + new RepresentationConverter(options.AllowOverflow, options.AllowTruncation))!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonISByteSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonISByteSerializerOptions.cs index 2f316f0..d60f7b5 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonISByteSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonISByteSerializerOptions.cs @@ -4,20 +4,21 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonISByteSerializerOptions : IBsonSerializerOptions +public record BsonISByteSerializerOptions : IBsonSerializerOptions { public DataType DataType { get; } = DataType.SByte; public BsonType Representation { get; set; } = BsonType.Int32; public Type SerializerType { get; set; } = typeof(BsonISByteSerializer<>); - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance - var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, Representation)!; + // Create an instance of the serializer + var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, options.Representation)!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIShortSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIShortSerializerOptions.cs index 413ecc1..408346a 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIShortSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIShortSerializerOptions.cs @@ -5,25 +5,26 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIShortSerializerOptions : IBsonSerializerOptions, IRepresentationConverterOptions +public record BsonIShortSerializerOptions : IBsonConvertibleSerializerOptions { public DataType DataType { get; } = DataType.Short; public BsonType Representation { get; set; } = BsonType.Int32; public Type SerializerType { get; set; } = typeof(BsonIShortSerializer<>); public bool AllowOverflow { get; set; } public bool AllowTruncation { get; set; } - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance + // Create an instance of the serializer var serializerInstance = (IBsonSerializer)Activator.CreateInstance( serializerType, - Representation, - new RepresentationConverter(AllowOverflow, AllowTruncation))!; + options.Representation, + new RepresentationConverter(options.AllowOverflow, options.AllowTruncation))!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIStringSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIStringSerializerOptions.cs index a45f5b1..1e15b91 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIStringSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIStringSerializerOptions.cs @@ -4,20 +4,21 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIStringSerializerOptions : IBsonSerializerOptions +public record BsonIStringSerializerOptions : IBsonSerializerOptions { public DataType DataType { get; } = DataType.String; public BsonType Representation { get; set; } = BsonType.String; public Type SerializerType { get; set; } = typeof(BsonIStringSerializer<>); - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance - var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, Representation)!; + // Create an instance of the serializer + var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, options.Representation)!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUIntSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUIntSerializerOptions.cs index 41ed3d7..0f73236 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUIntSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUIntSerializerOptions.cs @@ -5,25 +5,26 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIUIntSerializerOptions : IBsonSerializerOptions, IRepresentationConverterOptions +public record BsonIUIntSerializerOptions : IBsonConvertibleSerializerOptions { public DataType DataType { get; } = DataType.UInt; public BsonType Representation { get; set; } = BsonType.Int32; public Type SerializerType { get; set; } = typeof(BsonIUIntSerializer<>); public bool AllowOverflow { get; set; } public bool AllowTruncation { get; set; } - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance + // Create an instance of the serializer var serializerInstance = (IBsonSerializer)Activator.CreateInstance( serializerType, - Representation, - new RepresentationConverter(AllowOverflow, AllowTruncation))!; + options.Representation, + new RepresentationConverter(options.AllowOverflow, options.AllowTruncation))!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIULongSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIULongSerializerOptions.cs index 08e03bb..6f05dd5 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIULongSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIULongSerializerOptions.cs @@ -5,25 +5,26 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIULongSerializerOptions : IBsonSerializerOptions, IRepresentationConverterOptions +public record BsonIULongSerializerOptions : IBsonConvertibleSerializerOptions { public DataType DataType { get; } = DataType.ULong; public BsonType Representation { get; set; } = BsonType.Int64; public Type SerializerType { get; set; } = typeof(BsonIULongSerializer<>); public bool AllowOverflow { get; set; } public bool AllowTruncation { get; set; } - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance + // Create an instance of the serializer var serializerInstance = (IBsonSerializer)Activator.CreateInstance( serializerType, - Representation, - new RepresentationConverter(AllowOverflow, AllowTruncation))!; + options.Representation, + new RepresentationConverter(options.AllowOverflow, options.AllowTruncation))!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUShortSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUShortSerializerOptions.cs index b69edf3..af39e55 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUShortSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonIUShortSerializerOptions.cs @@ -5,25 +5,26 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; -public record BsonIUShortSerializerOptions : IBsonSerializerOptions, IRepresentationConverterOptions +public record BsonIUShortSerializerOptions : IBsonConvertibleSerializerOptions { public DataType DataType { get; } = DataType.UShort; public BsonType Representation { get; set; } = BsonType.Int32; public Type SerializerType { get; set; } = typeof(BsonIUShortSerializer<>); public bool AllowOverflow { get; set; } public bool AllowTruncation { get; set; } - - public virtual IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive + public Func CreateInstance { get; set; } = (options, primitiveType) => { - // Construct a Primitively serializer of the Primitively type - var serializerType = BsonOptions.GetSerializerType(SerializerType); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // Create a Primitively serializer instance + // Create an instance of the serializer var serializerInstance = (IBsonSerializer)Activator.CreateInstance( serializerType, - Representation, - new RepresentationConverter(AllowOverflow, AllowTruncation))!; + options.Representation, + new RepresentationConverter(options.AllowOverflow, options.AllowTruncation))!; return serializerInstance; - } + }; + + Func IBsonSerializerOptions.CreateInstance => (primitiveType) => CreateInstance.Invoke(this, primitiveType); } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonOptions.cs index 588cdc1..038309f 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonOptions.cs @@ -1,46 +1,142 @@ -namespace Primitively.MongoDB.Bson.Serialization.Options; +using MongoDB.Bson.Serialization.Serializers; +using MongoDB.Bson.Serialization; + +namespace Primitively.MongoDB.Bson.Serialization.Options; public class BsonOptions { + private static readonly List _primitiveTypes = new(); + public bool RegisterSerializersForEachTypeInRegistry { get; set; } = true; - public BsonIByteSerializerOptions BsonIByteSerializerOptions { get; set; } = new BsonIByteSerializerOptions(); - public BsonIDateOnlySerializerOptions BsonIDateOnlySerializerOptions { get; set; } = new BsonIDateOnlySerializerOptions(); - public BsonIGuidSerializerOptions BsonIGuidSerializerOptions { get; set; } = new BsonIGuidSerializerOptions(); - public BsonIIntSerializerOptions BsonIIntSerializerOptions { get; set; } = new BsonIIntSerializerOptions(); - public BsonILongSerializerOptions BsonILongSerializerOptions { get; set; } = new BsonILongSerializerOptions(); - public BsonISByteSerializerOptions BsonISByteSerializerOptions { get; set; } = new BsonISByteSerializerOptions(); - public BsonIShortSerializerOptions BsonIShortSerializerOptions { get; set; } = new BsonIShortSerializerOptions(); - public BsonIStringSerializerOptions BsonIStringSerializerOptions { get; set; } = new BsonIStringSerializerOptions(); - public BsonIUIntSerializerOptions BsonIUIntSerializerOptions { get; set; } = new BsonIUIntSerializerOptions(); - public BsonIULongSerializerOptions BsonIULongSerializerOptions { get; set; } = new BsonIULongSerializerOptions(); - public BsonIUShortSerializerOptions BsonIUShortSerializerOptions { get; set; } = new BsonIUShortSerializerOptions(); - internal Dictionary GetBsonSerializerOptions() => GetAll().ToDictionary(o => o.DataType, o => o); + public static Type GetSerializerType(Type primitiveType, Type serializerType) + { + // Construct a Bson serializer for the given Primitively type using the options + return serializerType.IsGenericTypeDefinition ? serializerType.MakeGenericType(primitiveType) : serializerType; + } - public static Type GetSerializerType(Type serializerType) where TPrimitive : struct, IPrimitive + public BsonOptions BsonIByteSerializer(Action options) { - // Construct a Primitively serializer of the Primitively type - return serializerType.IsGenericTypeDefinition ? serializerType.MakeGenericType(typeof(TPrimitive)) : serializerType; + var option = BsonSerializerOptionsCache.Get(DataType.Byte); + options.Invoke((BsonIByteSerializerOptions)option); + + return this; } - public static Type GetSerializerType(Type primitiveType, Type serializerType) + public BsonOptions BsonIDateOnlySerializer(Action options) { - // Construct a Primitively serializer of the Primitively type - return serializerType.IsGenericTypeDefinition ? serializerType.MakeGenericType(primitiveType) : serializerType; + var option = BsonSerializerOptionsCache.Get(DataType.DateOnly); + options.Invoke((BsonIDateOnlySerializerOptions)option); + + return this; } - private IEnumerable GetAll() + public BsonOptions BsonIGuidSerializer(Action options) { - yield return BsonIByteSerializerOptions; - yield return BsonIDateOnlySerializerOptions; - yield return BsonIGuidSerializerOptions; - yield return BsonIIntSerializerOptions; - yield return BsonILongSerializerOptions; - yield return BsonISByteSerializerOptions; - yield return BsonIShortSerializerOptions; - yield return BsonIStringSerializerOptions; - yield return BsonIUIntSerializerOptions; - yield return BsonIULongSerializerOptions; - yield return BsonIUShortSerializerOptions; + var option = BsonSerializerOptionsCache.Get(DataType.Guid); + options.Invoke((BsonIGuidSerializerOptions)option); + + return this; + } + + public BsonOptions BsonIIntSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.Int); + options.Invoke((BsonIIntSerializerOptions)option); + + return this; + } + + public BsonOptions BsonILongSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.Long); + options.Invoke((BsonILongSerializerOptions)option); + + return this; + } + + public BsonOptions BsonISByteSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.SByte); + options.Invoke((BsonISByteSerializerOptions)option); + + return this; + } + + public BsonOptions BsonIShortSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.Short); + options.Invoke((BsonIShortSerializerOptions)option); + + return this; + } + + public BsonOptions BsonIStringSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.String); + options.Invoke((BsonIStringSerializerOptions)option); + + return this; + } + + public BsonOptions BsonIUIntSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.UInt); + options.Invoke((BsonIUIntSerializerOptions)option); + + return this; + } + + public BsonOptions BsonIULongSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.ULong); + options.Invoke((BsonIULongSerializerOptions)option); + + return this; + } + + public BsonOptions BsonIUShortSerializer(Action options) + { + var option = BsonSerializerOptionsCache.Get(DataType.UShort); + options.Invoke((BsonIUShortSerializerOptions)option); + + return this; + } + + private BsonOptions RegisterSerializerForType(PrimitiveInfo primitiveInfo) + { + // Generate a nullable and non-nullable Bson serializer for the Primitively struct + var options = BsonSerializerOptionsCache.Get(primitiveInfo.DataType); + + RegisterSerializerForType(primitiveInfo.Type, options); + + return this; + } + + private static void RegisterSerializerForType(Type primitiveType, IBsonSerializerOptions options) + { + // Check that Primitive types has not been handled already + if (_primitiveTypes.Contains(primitiveType)) + { + return; + } + + // Add the type to a collection to provide a data source for the above check + _primitiveTypes.Add(primitiveType); + + // Create a Primitively serializer instance + var primitiveSerializerInstance = options.CreateInstance(primitiveType); + + // Register a Serializer for the Primitively type + BsonSerializer.TryRegisterSerializer(primitiveType, primitiveSerializerInstance); + + // Construct a nullable version of the Primitively type + var nullablePrimitiveType = typeof(Nullable<>).MakeGenericType(primitiveType); + + // Create a Nullable Primitively serializer instance + var nullablePrimitiveSerializerInstance = NullableSerializer.Create(primitiveSerializerInstance); + + // Register a NullableSerializer for a nullable version of the Primitively type + BsonSerializer.TryRegisterSerializer(nullablePrimitiveType, nullablePrimitiveSerializerInstance); } } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonSerializerOptionsCache.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonSerializerOptionsCache.cs new file mode 100644 index 0000000..25f7d6b --- /dev/null +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonSerializerOptionsCache.cs @@ -0,0 +1,25 @@ +using System.Collections.Concurrent; + +namespace Primitively.MongoDB.Bson.Serialization.Options; + +internal static class BsonSerializerOptionsCache +{ + private static readonly ConcurrentDictionary _items = new(GetAll().ToDictionary(o => o.DataType, o => o)); + + public static IBsonSerializerOptions Get(DataType dataType) => _items[dataType]; + + private static IEnumerable GetAll() + { + yield return new BsonIByteSerializerOptions(); + yield return new BsonIDateOnlySerializerOptions(); + yield return new BsonIGuidSerializerOptions(); + yield return new BsonIIntSerializerOptions(); + yield return new BsonILongSerializerOptions(); + yield return new BsonISByteSerializerOptions(); + yield return new BsonIShortSerializerOptions(); + yield return new BsonIStringSerializerOptions(); + yield return new BsonIUIntSerializerOptions(); + yield return new BsonIULongSerializerOptions(); + yield return new BsonIUShortSerializerOptions(); + } +} diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/BsonSerializerOptionsExtensions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonSerializerOptionsExtensions.cs new file mode 100644 index 0000000..eeef0a8 --- /dev/null +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/BsonSerializerOptionsExtensions.cs @@ -0,0 +1,49 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization; + +namespace Primitively.MongoDB.Bson.Serialization.Options; + +public static class BsonSerializerOptionsExtensions +{ + public static IBsonSerializerOptions AllowOverflow(this IBsonConvertibleSerializerOptions options, bool allowOverflow) + where TOptions : IBsonSerializerOptions + { + options.AllowOverflow = allowOverflow; + return options; + } + + public static IBsonSerializerOptions AllowTruncation(this IBsonConvertibleSerializerOptions options, bool allowTruncation) + where TOptions : IBsonSerializerOptions + { + options.AllowTruncation = allowTruncation; + return options; + } + + public static IBsonSerializerOptions CreateInstanceWith(this IBsonSerializerOptions options, Func createInstance) + where TOptions : IBsonSerializerOptions + { + options.CreateInstance = createInstance; + return options; + } + + public static IBsonSerializerOptions RepresentAs(this IBsonSerializerOptions options, BsonType representation) + where TOptions : IBsonSerializerOptions + { + options.Representation = representation; + return options; + } + + public static IBsonSerializerOptions RepresentAs(this IBsonIGuidSerializerOptions options, GuidRepresentation representation) + where TOptions : IBsonSerializerOptions + { + options.GuidRepresentation = representation; + return options; + } + + public static IBsonSerializerOptions SerializeWith(this IBsonSerializerOptions options, Type serializerType) + where TOptions : IBsonSerializerOptions + { + options.SerializerType = serializerType; + return options; + } +} diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonConvertibleSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonConvertibleSerializerOptions.cs new file mode 100644 index 0000000..190fa94 --- /dev/null +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonConvertibleSerializerOptions.cs @@ -0,0 +1,8 @@ +namespace Primitively.MongoDB.Bson.Serialization.Options; + +public interface IBsonConvertibleSerializerOptions : IBsonSerializerOptions + where TOptions : IBsonSerializerOptions +{ + bool AllowOverflow { get; internal set; } + bool AllowTruncation { get; internal set; } +} diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonIGuidSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonIGuidSerializerOptions.cs new file mode 100644 index 0000000..d2d5a8d --- /dev/null +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonIGuidSerializerOptions.cs @@ -0,0 +1,9 @@ +using MongoDB.Bson; + +namespace Primitively.MongoDB.Bson.Serialization.Options; + +public interface IBsonIGuidSerializerOptions : IBsonSerializerOptions + where TOptions : IBsonSerializerOptions +{ + GuidRepresentation GuidRepresentation { get; internal set; } +} diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonSerializerOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonSerializerOptions.cs index 5c41833..0f27626 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonSerializerOptions.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonSerializerOptions.cs @@ -6,8 +6,7 @@ namespace Primitively.MongoDB.Bson.Serialization.Options; public interface IBsonSerializerOptions { DataType DataType { get; } - BsonType Representation { get; set; } - Type SerializerType { get; set; } - //Func CreateInstance { get; set; } - IBsonSerializer CreateInstance() where TPrimitive : struct, IPrimitive; + BsonType Representation { get; internal set; } + Type SerializerType { get; internal set; } + Func CreateInstance { get; } } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonSerializerOptions`1.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonSerializerOptions`1.cs new file mode 100644 index 0000000..47f609a --- /dev/null +++ b/src/Primitively.MongoDB.Bson/Serialization/Options/IBsonSerializerOptions`1.cs @@ -0,0 +1,9 @@ +using MongoDB.Bson.Serialization; + +namespace Primitively.MongoDB.Bson.Serialization.Options; + +public interface IBsonSerializerOptions : IBsonSerializerOptions + where TOptions : IBsonSerializerOptions +{ + new Func CreateInstance { get; set; } +} diff --git a/src/Primitively.MongoDB.Bson/Serialization/Options/IRepresentationConverterOptions.cs b/src/Primitively.MongoDB.Bson/Serialization/Options/IRepresentationConverterOptions.cs deleted file mode 100644 index 7f1cb5c..0000000 --- a/src/Primitively.MongoDB.Bson/Serialization/Options/IRepresentationConverterOptions.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Primitively.MongoDB.Bson.Serialization.Options; - -public interface IRepresentationConverterOptions -{ - bool AllowOverflow { get; set; } - bool AllowTruncation { get; set; } -} diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIByteSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIByteSerializer.cs index ecc65ca..3dfe0bf 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIByteSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIByteSerializer.cs @@ -7,8 +7,9 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a Byte value. /// -public class BsonIByteSerializer : StructSerializerBase, IRepresentationConfigurable> - where TPrimitive : struct, IByte +public class BsonIByteSerializer : + StructSerializerBase, + IRepresentationConfigurable> where TPrimitive : struct, IByte { private readonly ByteSerializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIDateOnlySerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIDateOnlySerializer.cs index e23f45d..1827425 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIDateOnlySerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIDateOnlySerializer.cs @@ -7,8 +7,9 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a DateOnly value. /// -public class BsonIDateOnlySerializer : StructSerializerBase, IRepresentationConfigurable> - where TPrimitive : struct, IDateOnly +public class BsonIDateOnlySerializer : + StructSerializerBase, + IRepresentationConfigurable> where TPrimitive : struct, IDateOnly { private readonly DateTimeSerializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIGuidSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIGuidSerializer.cs index 186122e..4ac3952 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIGuidSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIGuidSerializer.cs @@ -7,36 +7,31 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a Guid value. /// -public class BsonIGuidSerializer : StructSerializerBase, IRepresentationConfigurable>, IGuidRepresentationConfigurable> - where TPrimitive : struct, IGuid +public class BsonIGuidSerializer : + StructSerializerBase, + IRepresentationConfigurable>, + IGuidRepresentationConfigurable> where TPrimitive : struct, IGuid { - private readonly Lazy _serializer; - - /// - /// Initializes a new instance of the class. - /// - /// - /// This defaults to BsonType.Binary and GuidRepresentation.Standard. - /// - public BsonIGuidSerializer() : this(BsonSerializer.SerializerRegistry) { } + private readonly GuidSerializer _serializer; /// /// Initializes a new instance of the class. /// /// The serializer. - public BsonIGuidSerializer(GuidSerializer serializer) + private BsonIGuidSerializer(GuidSerializer serializer) { - _serializer = new Lazy(() => serializer); + _serializer = serializer; } - public BsonIGuidSerializer(IBsonSerializerRegistry serializerRegistry) + /// + /// Initializes a new instance of the class. + /// + /// + /// This defaults to BsonType.Binary and GuidRepresentation.Standard. + /// + public BsonIGuidSerializer() { - if (serializerRegistry is null) - { - throw new ArgumentNullException(nameof(serializerRegistry)); - } - - _serializer = new Lazy(() => (GuidSerializer)serializerRegistry.GetSerializer()); + _serializer = new GuidSerializer(); } /// @@ -45,7 +40,7 @@ public BsonIGuidSerializer(IBsonSerializerRegistry serializerRegistry) /// The representation. public BsonIGuidSerializer(BsonType representation) { - _serializer = new Lazy(() => new GuidSerializer(representation)); + _serializer = new GuidSerializer(representation); } /// @@ -54,23 +49,23 @@ public BsonIGuidSerializer(BsonType representation) /// The Guid representation. public BsonIGuidSerializer(GuidRepresentation guidRepresentation) { - _serializer = new Lazy(() => new GuidSerializer(guidRepresentation)); + _serializer = new GuidSerializer(guidRepresentation); } /// - /// Gets a cached instance of the class with standard representation. + /// Gets a cached instance of the class with standard representation. /// public static BsonIGuidSerializer Instance { get; } = new(); /// /// Gets the Guid representation. /// - public GuidRepresentation GuidRepresentation => _serializer.Value.GuidRepresentation; + public GuidRepresentation GuidRepresentation => _serializer.GuidRepresentation; /// /// Gets the representation. /// - public BsonType Representation => _serializer.Value.Representation; + public BsonType Representation => _serializer.Representation; /// /// Initializes a new instance of the class. @@ -86,7 +81,7 @@ public BsonIGuidSerializer(GuidRepresentation guidRepresentation) /// A deserialized value. public override TPrimitive Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { - var value = _serializer.Value.Deserialize(context, args); + var value = _serializer.Deserialize(context, args); return (TPrimitive)Activator.CreateInstance(typeof(TPrimitive), value)!; } @@ -99,7 +94,7 @@ public override TPrimitive Deserialize(BsonDeserializationContext context, BsonD /// The object. public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TPrimitive value) { - _serializer.Value.Serialize(context, args, value.Value); + _serializer.Serialize(context, args, value.Value); } /// @@ -109,7 +104,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati /// The reconfigured serializer. public BsonIGuidSerializer WithGuidRepresentation(GuidRepresentation guidRepresentation) { - if (guidRepresentation == _serializer.Value.GuidRepresentation) + if (guidRepresentation == _serializer.GuidRepresentation) { return this; } @@ -124,7 +119,7 @@ public BsonIGuidSerializer WithGuidRepresentation(GuidRepresentation /// The reconfigured serializer. public BsonIGuidSerializer WithRepresentation(BsonType representation) { - if (representation == _serializer.Value.Representation) + if (representation == _serializer.Representation) { return this; } diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIIntSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIIntSerializer.cs index 6da7e5a..0cc9fa3 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIIntSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIIntSerializer.cs @@ -8,8 +8,10 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a Int value. /// -public class BsonIIntSerializer : StructSerializerBase, IRepresentationConfigurable>, IRepresentationConverterConfigurable> - where TPrimitive : struct, IInt +public class BsonIIntSerializer : + StructSerializerBase, + IRepresentationConfigurable>, + IRepresentationConverterConfigurable> where TPrimitive : struct, IInt { private readonly Int32Serializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonILongSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonILongSerializer.cs index e6a3274..df6c45d 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonILongSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonILongSerializer.cs @@ -8,8 +8,10 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a Long value. /// -public class BsonILongSerializer : StructSerializerBase, IRepresentationConfigurable>, IRepresentationConverterConfigurable> - where TPrimitive : struct, ILong +public class BsonILongSerializer : + StructSerializerBase, + IRepresentationConfigurable>, + IRepresentationConverterConfigurable> where TPrimitive : struct, ILong { private readonly Int64Serializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonISByteSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonISByteSerializer.cs index 24569c7..42934ee 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonISByteSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonISByteSerializer.cs @@ -7,8 +7,9 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a SByte value. /// -public class BsonISByteSerializer : StructSerializerBase, IRepresentationConfigurable> - where TPrimitive : struct, ISByte +public class BsonISByteSerializer : + StructSerializerBase, + IRepresentationConfigurable> where TPrimitive : struct, ISByte { private readonly SByteSerializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIShortSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIShortSerializer.cs index 5ca1492..5e91b28 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIShortSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIShortSerializer.cs @@ -8,8 +8,10 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a Short value. /// -public class BsonIShortSerializer : StructSerializerBase, IRepresentationConfigurable>, IRepresentationConverterConfigurable> - where TPrimitive : struct, IShort +public class BsonIShortSerializer : + StructSerializerBase, + IRepresentationConfigurable>, + IRepresentationConverterConfigurable> where TPrimitive : struct, IShort { private readonly Int16Serializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIStringSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIStringSerializer.cs index b91954a..950116f 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIStringSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIStringSerializer.cs @@ -7,8 +7,9 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a String value. /// -public class BsonIStringSerializer : StructSerializerBase, IRepresentationConfigurable> - where TPrimitive : struct, IString +public class BsonIStringSerializer : + StructSerializerBase, + IRepresentationConfigurable> where TPrimitive : struct, IString { private readonly StringSerializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUIntSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUIntSerializer.cs index 2a6372b..bd84750 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUIntSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUIntSerializer.cs @@ -8,8 +8,10 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a UInt value. /// -public class BsonIUIntSerializer : StructSerializerBase, IRepresentationConfigurable>, IRepresentationConverterConfigurable> - where TPrimitive : struct, IUInt +public class BsonIUIntSerializer : + StructSerializerBase, + IRepresentationConfigurable>, + IRepresentationConverterConfigurable> where TPrimitive : struct, IUInt { private readonly UInt32Serializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIULongSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIULongSerializer.cs index e03e5f7..28c5d4d 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIULongSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIULongSerializer.cs @@ -8,8 +8,10 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a ULong value. /// -public class BsonIULongSerializer : StructSerializerBase, IRepresentationConfigurable>, IRepresentationConverterConfigurable> - where TPrimitive : struct, IULong +public class BsonIULongSerializer : + StructSerializerBase, + IRepresentationConfigurable>, + IRepresentationConverterConfigurable> where TPrimitive : struct, IULong { private readonly UInt64Serializer _serializer; diff --git a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUShortSerializer.cs b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUShortSerializer.cs index 240e6b3..42590f2 100644 --- a/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUShortSerializer.cs +++ b/src/Primitively.MongoDB.Bson/Serialization/Serializers/BsonIUShortSerializer.cs @@ -8,8 +8,10 @@ namespace Primitively.MongoDB.Bson.Serialization.Serializers; /// /// Represents a serializer for Primitively types that encapsulate a UShort value. /// -public class BsonIUShortSerializer : StructSerializerBase, IRepresentationConfigurable>, IRepresentationConverterConfigurable> - where TPrimitive : struct, IUShort +public class BsonIUShortSerializer : + StructSerializerBase, + IRepresentationConfigurable>, + IRepresentationConverterConfigurable> where TPrimitive : struct, IUShort { private readonly UInt16Serializer _serializer; diff --git a/test/Primitively.IntegrationTests/PrimitiveBsonSerializerTests.cs b/test/Primitively.IntegrationTests/PrimitiveBsonSerializerTests.cs index 4489c5b..87b5215 100644 --- a/test/Primitively.IntegrationTests/PrimitiveBsonSerializerTests.cs +++ b/test/Primitively.IntegrationTests/PrimitiveBsonSerializerTests.cs @@ -1,9 +1,11 @@ using FluentAssertions; using Microsoft.Extensions.DependencyInjection; +using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; using Primitively.Configuration; using Primitively.MongoDB.Bson; +using Primitively.MongoDB.Bson.Serialization.Options; using Primitively.MongoDB.Bson.Serialization.Serializers; using Xunit; @@ -11,7 +13,7 @@ namespace Primitively.IntegrationTests; public class PrimitiveBsonSerializerTests { - [Fact] + [Fact(Skip = "Still in developement")] public void BsonSerializers_Types_Are_Registered_Correctly_Using_IPrimitive_Instances_In_Params() { // Arrange @@ -24,46 +26,54 @@ public void BsonSerializers_Types_Are_Registered_Correctly_Using_IPrimitive_Inst // Act services.AddPrimitively() - .AddBson(configure => + .AddBson(options => { - // Add MongoDB support and register BSON serializers for the given source generated Primitive types - configure.DefaultSerializers(cache => - { - // Override default serializers by replacing the item in the cache (Nb. Re-adding the default rather - // than creating and assigning a new type). This method does not need to be called unless a custom serializer is preferred - cache.SetSerializer(DataType.DateOnly, typeof(BsonIDateOnlySerializer<>)); - cache.SetSerializer(DataType.Guid, typeof(BsonIGuidSerializer<>)); - cache.SetSerializer(DataType.Int, typeof(BsonIIntSerializer<>)); - cache.SetSerializer(DataType.Long, typeof(BsonILongSerializer<>)); - cache.SetSerializer(DataType.SByte, typeof(BsonISByteSerializer<>)); - cache.SetSerializer(DataType.Short, typeof(BsonIShortSerializer<>)); - cache.SetSerializer(DataType.String, typeof(BsonIStringSerializer<>)); - cache.SetSerializer(DataType.UInt, typeof(BsonIUIntSerializer<>)); - cache.SetSerializer(DataType.ULong, typeof(BsonIULongSerializer<>)); - cache.SetSerializer(DataType.UShort, typeof(BsonIUShortSerializer<>)); - }); + options.BsonIByteSerializer(option => option.RepresentAs(BsonType.Int32)); + options.BsonIGuidSerializer(option => option + .RepresentAs(GuidRepresentation.Standard) + .SerializeWith(typeof(BsonIGuidSerializer<>)) + .CreateInstanceWith((options, primitiveType) => + { + // Check that the application is using the correct GuidRepresentationMode + if (options.GuidRepresentation != BsonDefaults.GuidRepresentation && BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2) + { + // V3 mode permits a mixture of searchable GUID representations to exist side by side + // TODO: Consider throwing an exception instead rather than forcing the mode to V3 + BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3; + } - configure.RegisterSerializers(register => - { - // Create an instance of a Bson Serializer for the given Primitively types using the configured - // Bson Serializers held in the BsonSerializerCache - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); - register.AddSerializerForType(); + // Construct a Bson serializer for the given Primitively type using the options + var serializerType = BsonOptions.GetSerializerType(primitiveType, options.SerializerType); - // User serializer defined in the IBsonSerializer type parameter - register.AddSerializerForType>(); + // Create an instance of the serializer + object argument = options.Representation == BsonType.String ? BsonType.String : options.GuidRepresentation; + var serializerInstance = (IBsonSerializer)Activator.CreateInstance(serializerType, argument)!; - // Create an instance of a Bson Serializer for each Primitively type in the given Primitively repo - register.AddSerializerForEachTypeIn(); - }); + return serializerInstance; + })); + options.BsonIIntSerializer(options => options.AllowOverflow = true); + + //configure.RegisterSerializers(register => + //{ + // // Create an instance of a Bson Serializer for the given Primitively types using the configured + // // Bson Serializers held in the BsonSerializerCache + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + // register.AddSerializerForType(); + + // // User serializer defined in the IBsonSerializer type parameter + // register.AddSerializerForType>(); + + // // Create an instance of a Bson Serializer for each Primitively type in the given Primitively repo + // register.AddSerializerForEachTypeIn(); + //}); }); // Assert diff --git a/test/Primitively.IntegrationTests/Primitively.IntegrationTests.csproj b/test/Primitively.IntegrationTests/Primitively.IntegrationTests.csproj index 25185b0..eb6885b 100644 --- a/test/Primitively.IntegrationTests/Primitively.IntegrationTests.csproj +++ b/test/Primitively.IntegrationTests/Primitively.IntegrationTests.csproj @@ -8,7 +8,7 @@ false Generated true - $(NoWarn);CA1825 + $(NoWarn);CA1825;CS0618