Skip to content

Commit

Permalink
Extended the MongoDB serializer support. (#5)
Browse files Browse the repository at this point in the history
Extended the MongoDB serializer support with the configuration of the representation type.
  • Loading branch information
mgernand authored Jun 3, 2022
1 parent 71fbcbd commit bb80a33
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Fluxera.StronglyTypedId.MongoDB
{
using global::MongoDB.Bson;
using global::MongoDB.Bson.Serialization.Conventions;
using JetBrains.Annotations;

Expand All @@ -13,10 +14,14 @@ public static class ConventionPackExtensions
/// Configure the serializer to use the <see cref="StronglyTypedIdSerializer{TStronglyTypedId,TValue}" />.
/// </summary>
/// <param name="pack"></param>
/// <param name="stringRepresentation"></param>
/// <param name="guidRepresentation"></param>
/// <returns></returns>
public static ConventionPack UseStronglyTypedId(this ConventionPack pack)
public static ConventionPack UseStronglyTypedId(this ConventionPack pack,
BsonType stringRepresentation = BsonType.ObjectId,
GuidRepresentation guidRepresentation = GuidRepresentation.Standard)
{
pack.Add(new StronglyTypedIdConvention());
pack.Add(new StronglyTypedIdConvention(stringRepresentation, guidRepresentation));

return pack;
}
Expand Down
38 changes: 36 additions & 2 deletions src/Fluxera.StronglyTypedId.MongoDB/StronglyTypedIdConvention.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
namespace Fluxera.StronglyTypedId.MongoDB
{
using System;
using Fluxera.Utilities.Extensions;
using global::MongoDB.Bson;
using global::MongoDB.Bson.Serialization;
using global::MongoDB.Bson.Serialization.Conventions;
using global::MongoDB.Bson.Serialization.Serializers;
using JetBrains.Annotations;

/// <summary>
Expand All @@ -11,19 +14,50 @@
[PublicAPI]
public sealed class StronglyTypedIdConvention : ConventionBase, IMemberMapConvention
{
private readonly IBsonSerializer guidSerializer;
private readonly IBsonSerializer stringSerializer;

/// <summary>
/// Initializes a new instance of the <see cref="StronglyTypedIdConvention" /> type.
/// </summary>
/// <param name="stringRepresentation"></param>
/// <param name="guidRepresentation"></param>
public StronglyTypedIdConvention(
BsonType stringRepresentation = BsonType.ObjectId,
GuidRepresentation guidRepresentation = GuidRepresentation.Standard)
{
this.stringSerializer = new StringSerializer(stringRepresentation);
this.guidSerializer = new GuidSerializer(guidRepresentation);
}

/// <inheritdoc />
public void Apply(BsonMemberMap memberMap)
{
Type originalMemberType = memberMap.MemberType;
Type memberType = Nullable.GetUnderlyingType(originalMemberType) ?? originalMemberType;
Type memberType = originalMemberType.UnwrapNullableType();

if(memberType.IsStronglyTypedId())
{
Type valueType = memberType.GetValueType();
Type serializerTypeTemplate = typeof(StronglyTypedIdSerializer<,>);
Type serializerType = serializerTypeTemplate.MakeGenericType(memberType, valueType);

IBsonSerializer enumerationSerializer = (IBsonSerializer)Activator.CreateInstance(serializerType);
IBsonSerializer serializer;

if(valueType == typeof(string))
{
serializer = this.stringSerializer;
}
else if(valueType == typeof(Guid))
{
serializer = this.guidSerializer;
}
else
{
serializer = BsonSerializer.LookupSerializer(valueType);
}

IBsonSerializer enumerationSerializer = (IBsonSerializer)Activator.CreateInstance(serializerType, new object[] { serializer });
memberMap.SetSerializer(enumerationSerializer);
}
}
Expand Down
32 changes: 30 additions & 2 deletions src/Fluxera.StronglyTypedId.MongoDB/StronglyTypedIdSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ public sealed class StronglyTypedIdSerializer<TStronglyTypedId, TValue> : Serial
where TStronglyTypedId : StronglyTypedId<TStronglyTypedId, TValue>
where TValue : IComparable
{
private readonly IBsonSerializer idValueSerializer;

/// <summary>
/// Initializes a new instance of the <see cref="StronglyTypedIdSerializer{TStronglyTypedId,TValue}" />;
/// </summary>
/// <param name="idValueSerializer"></param>
public StronglyTypedIdSerializer(IBsonSerializer idValueSerializer)
{
this.idValueSerializer = idValueSerializer;
}

/// <inheritdoc />
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TStronglyTypedId value)
{
Expand All @@ -25,7 +36,14 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati
}
else
{
BsonSerializer.Serialize(context.Writer, value.Value);
if(this.idValueSerializer != null)
{
this.idValueSerializer.Serialize(context, args, value.Value);
}
else
{
BsonSerializer.Serialize(context.Writer, value.Value);
}
}
}

Expand All @@ -38,7 +56,17 @@ public override TStronglyTypedId Deserialize(BsonDeserializationContext context,
return null;
}

TValue value = BsonSerializer.Deserialize<TValue>(context.Reader);
TValue value;

if(this.idValueSerializer != null)
{
value = (TValue)this.idValueSerializer.Deserialize(context, args);
}
else
{
value = BsonSerializer.Deserialize<TValue>(context.Reader);
}

object instance = Activator.CreateInstance(args.NominalType, new object[] { value });
return (TStronglyTypedId)instance;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Fluxera.StronglyTypedId/IStronglyTypedId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// <typeparam name="TKey"></typeparam>
[PublicAPI]
public interface IStronglyTypedId<TStronglyTypedId, out TKey> : IComparable<TStronglyTypedId>, IEquatable<TStronglyTypedId>
where TKey : notnull
where TKey : notnull, IComparable
{
/// <summary>
/// Gets the underlying value of the strongly-typed ID.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ public class TestClass

private static readonly TestClass TestInstance = new TestClass
{
PersonId = new PersonId("12345")
PersonId = new PersonId("6299e4fda14ed1025f7a413e")
};

private static readonly string JsonString = @"{ ""PersonId"" : ""12345"" }";
private static readonly string JsonString = @"{ ""PersonId"" : ObjectId(""6299e4fda14ed1025f7a413e"") }";

[Test]
public void ShouldDeserialize()
{
TestClass obj = BsonSerializer.Deserialize<TestClass>(JsonString);

obj.PersonId.Should().Be(new PersonId("12345"));
obj.PersonId.Should().Be(new PersonId("6299e4fda14ed1025f7a413e"));
}

[Test]
Expand Down

0 comments on commit bb80a33

Please sign in to comment.