diff --git a/src/Context.AllowedTypes.Tests/Helpers/TestHelpers.cs b/src/Context.AllowedTypes.Tests/Helpers/TestHelpers.cs index fad2d47..1d0364f 100644 --- a/src/Context.AllowedTypes.Tests/Helpers/TestHelpers.cs +++ b/src/Context.AllowedTypes.Tests/Helpers/TestHelpers.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using MongoDB.Extensions.Context.Internal; namespace MongoDB.Extensions.Context.AllowedTypes.Tests.Helpers; diff --git a/src/Context.AllowedTypes.Tests/MongoDatabaseBuilderTests.cs b/src/Context.AllowedTypes.Tests/MongoDatabaseBuilderTests.cs index 9446c28..57f7b9a 100644 --- a/src/Context.AllowedTypes.Tests/MongoDatabaseBuilderTests.cs +++ b/src/Context.AllowedTypes.Tests/MongoDatabaseBuilderTests.cs @@ -3,7 +3,6 @@ using MongoDB.Bson.Serialization; using MongoDB.Driver; using MongoDB.Extensions.Context.AllowedTypes.Tests.Helpers; -using MongoDB.Extensions.Context.Internal; using Snapshooter.Xunit; using Squadron; using Xunit; diff --git a/src/Context.AllowedTypes.Tests/TypeObjectSerializerTests.cs b/src/Context.AllowedTypes.Tests/TypeObjectSerializerTests.cs index 05bd422..08009bc 100644 --- a/src/Context.AllowedTypes.Tests/TypeObjectSerializerTests.cs +++ b/src/Context.AllowedTypes.Tests/TypeObjectSerializerTests.cs @@ -1,5 +1,4 @@ using MongoDB.Extensions.Context.AllowedTypes.Tests.Helpers; -using MongoDB.Extensions.Context.Internal; using Snapshooter.Xunit; using Xunit; diff --git a/src/Context.GuidSerializer.Tests/Context.GuidSerializers.Tests.csproj b/src/Context.GuidSerializer.Tests/Context.GuidSerializers.Tests.csproj new file mode 100644 index 0000000..f18a54c --- /dev/null +++ b/src/Context.GuidSerializer.Tests/Context.GuidSerializers.Tests.csproj @@ -0,0 +1,18 @@ + + + + + MongoDB.Extensions.Context.GuidSerializers.Tests + MongoDB.Extensions.Context.GuidSerializers.Tests + + + + + + + + + + + + diff --git a/src/Context.GuidSerializer.Tests/GuidSerializerTests.cs b/src/Context.GuidSerializer.Tests/GuidSerializerTests.cs new file mode 100644 index 0000000..62335fc --- /dev/null +++ b/src/Context.GuidSerializer.Tests/GuidSerializerTests.cs @@ -0,0 +1,71 @@ +using MongoDB.Driver; +using Squadron; +using Xunit; +using System; +using System.Threading.Tasks; +using Snapshooter.Xunit; +using MongoDB.Prime.Extensions; + +namespace MongoDB.Extensions.Context.GuidSerializers.Tests; + +public class GuidSerializerTests : IClassFixture +{ + private readonly MongoOptions _mongoOptions; + private readonly IMongoDatabase _mongoDatabase; + + public GuidSerializerTests(MongoResource mongoResource) + { + _mongoDatabase = mongoResource.CreateDatabase(); + _mongoOptions = new MongoOptions + { + ConnectionString = mongoResource.ConnectionString, + DatabaseName = _mongoDatabase.DatabaseNamespace.DatabaseName + }; + } + + [Fact] + public async Task Serialize_GuidPropertyGuidSerialized_Successfully() + { + // Arrange + var foobarMongoDbContext = new FooBarMongoDbContext(_mongoOptions); + + IMongoCollection collection = + _mongoDatabase.GetCollection("foos"); + + Foo foo = new Foo + ( + fooId: Guid.Parse("b1eba0d6-a1f9-4e31-bd70-0feed19f4492"), + name: "test", + additionalId: Guid.Parse("b58ec857-c874-457e-8662-133a055282f6") + ); + + // Act + await collection.InsertOneAsync(foo); + + // Assert + Snapshot.Match(collection.Dump()); + } + + [Fact] + public async Task Serialize_ObjectPropertyGuidSerialized_Successfully() + { + // Arrange + var foobarMongoDbContext = new FooBarMongoDbContext(_mongoOptions); + + IMongoCollection collection = + _mongoDatabase.GetCollection("bars"); + + Bar bar = new Bar + ( + fooId: Guid.Parse("b1eba0d6-a1f9-4e31-bd70-0feed19f4492"), + name: "test", + additionalId: Guid.Parse("b58ec857-c874-457e-8662-133a055282f6") + ); + + // Act + await collection.InsertOneAsync(bar); + + // Assert + Snapshot.Match(collection.Dump()); + } +} diff --git a/src/Context.GuidSerializer.Tests/Helpers/Bar.cs b/src/Context.GuidSerializer.Tests/Helpers/Bar.cs new file mode 100644 index 0000000..3fe32f0 --- /dev/null +++ b/src/Context.GuidSerializer.Tests/Helpers/Bar.cs @@ -0,0 +1,19 @@ +using System; + +namespace MongoDB.Extensions.Context.GuidSerializers.Tests; + +public class Bar +{ + public Bar(Guid fooId, string name, Guid additionalId) + { + Id = fooId; + Name = name; + AdditionalId = additionalId; + } + + public Guid Id { get; private set; } + + public string Name { get; private set;} + + public object AdditionalId { get; private set;} +} diff --git a/src/Context.GuidSerializer.Tests/Helpers/Foo.cs b/src/Context.GuidSerializer.Tests/Helpers/Foo.cs new file mode 100644 index 0000000..e5ced83 --- /dev/null +++ b/src/Context.GuidSerializer.Tests/Helpers/Foo.cs @@ -0,0 +1,19 @@ +using System; + +namespace MongoDB.Extensions.Context.GuidSerializers.Tests; + +public class Foo +{ + public Foo(Guid fooId, string name, Guid additionalId) + { + Id = fooId; + Name = name; + AdditionalId = additionalId; + } + + public Guid Id { get; private set; } + + public string Name { get; private set;} + + public Guid AdditionalId { get; private set;} +} diff --git a/src/Context.GuidSerializer.Tests/Helpers/FooBarMongoDbContext.cs b/src/Context.GuidSerializer.Tests/Helpers/FooBarMongoDbContext.cs new file mode 100644 index 0000000..f21b813 --- /dev/null +++ b/src/Context.GuidSerializer.Tests/Helpers/FooBarMongoDbContext.cs @@ -0,0 +1,18 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Serializers; + +namespace MongoDB.Extensions.Context.GuidSerializers.Tests; + +public class FooBarMongoDbContext : MongoDbContext +{ + public FooBarMongoDbContext(MongoOptions mongoOptions) + : base(mongoOptions) + { + } + + protected override void OnConfiguring( + IMongoDatabaseBuilder databaseBuilder) + { + databaseBuilder.RegisterSerializer(new GuidSerializer(GuidRepresentation.CSharpLegacy)); + } +} diff --git a/src/Context.GuidSerializer.Tests/__snapshots__/GuidSerializerTests.Serialize_GuidPropertyGuidSerialized_Successfully.snap b/src/Context.GuidSerializer.Tests/__snapshots__/GuidSerializerTests.Serialize_GuidPropertyGuidSerialized_Successfully.snap new file mode 100644 index 0000000..16763f9 --- /dev/null +++ b/src/Context.GuidSerializer.Tests/__snapshots__/GuidSerializerTests.Serialize_GuidPropertyGuidSerialized_Successfully.snap @@ -0,0 +1,7 @@ +[ + { + "Id": "b1eba0d6-a1f9-4e31-bd70-0feed19f4492", + "Name": "test", + "AdditionalId": "b58ec857-c874-457e-8662-133a055282f6" + } +] diff --git a/src/Context.GuidSerializer.Tests/__snapshots__/GuidSerializerTests.Serialize_ObjectPropertyGuidSerialized_Successfully.snap b/src/Context.GuidSerializer.Tests/__snapshots__/GuidSerializerTests.Serialize_ObjectPropertyGuidSerialized_Successfully.snap new file mode 100644 index 0000000..16763f9 --- /dev/null +++ b/src/Context.GuidSerializer.Tests/__snapshots__/GuidSerializerTests.Serialize_ObjectPropertyGuidSerialized_Successfully.snap @@ -0,0 +1,7 @@ +[ + { + "Id": "b1eba0d6-a1f9-4e31-bd70-0feed19f4492", + "Name": "test", + "AdditionalId": "b58ec857-c874-457e-8662-133a055282f6" + } +] diff --git a/src/Context/Internal/TypeObjectSerializer.cs b/src/Context/Internal/TypeObjectSerializer.cs index 1badd95..0029d82 100644 --- a/src/Context/Internal/TypeObjectSerializer.cs +++ b/src/Context/Internal/TypeObjectSerializer.cs @@ -1,6 +1,6 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; +using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Conventions; using MongoDB.Bson.Serialization.Serializers; @@ -8,9 +8,9 @@ #nullable enable -namespace MongoDB.Extensions.Context.Internal; +namespace MongoDB.Extensions.Context; -internal class TypeObjectSerializer : ClassSerializerBase, IHasDiscriminatorConvention +public class TypeObjectSerializer : ClassSerializerBase, IHasDiscriminatorConvention { private readonly ObjectSerializer _objectSerializer; private static readonly Dictionary _allowedTypes = new(); @@ -18,9 +18,10 @@ internal class TypeObjectSerializer : ClassSerializerBase, IHasDiscrimin private static readonly HashSet _allowedTypesByDependencies = new(); private static readonly object _lock = new(); - public TypeObjectSerializer() + public TypeObjectSerializer(ObjectSerializer? objectSerializer = null) { - _objectSerializer = new ObjectSerializer(type => IsTypeAllowed(type)); + _objectSerializer = objectSerializer ?? CreateObjectSerializer(); + DiscriminatorConvention = _objectSerializer.GetDiscriminatorConvention(); } @@ -47,7 +48,7 @@ public static bool IsTypeAllowed(Type type) public static void AddAllowedType() { lock (_lock) - { + { _allowedTypes.Add(typeof(T), true); } } @@ -67,7 +68,7 @@ public static void AddAllowedTypes(params string[] allowedNamespaces) { lock (_lock) { - foreach (string allowedNamespace in allowedNamespaces) + foreach (var allowedNamespace in allowedNamespaces) { _allowedTypesByNamespaces.Add(allowedNamespace); } @@ -160,4 +161,24 @@ public override int GetHashCode() { return _objectSerializer.GetHashCode(); } + + private ObjectSerializer CreateObjectSerializer() + { + IDiscriminatorConvention objectDiscriminatorConvention = + BsonSerializer.LookupDiscriminatorConvention(typeof(object)); + + var serializer = + BsonSerializer.LookupSerializer(typeof(Guid)) as GuidSerializer; + + GuidRepresentation guidRepresentation = + serializer?.GuidRepresentation ?? GuidRepresentation.Unspecified; + + var objectSerializer = + new ObjectSerializer( + objectDiscriminatorConvention, + guidRepresentation, + type => IsTypeAllowed(type)); + + return objectSerializer; + } } diff --git a/src/MongoDB.Extensions.sln b/src/MongoDB.Extensions.sln index 22ffd3a..7edb04e 100644 --- a/src/MongoDB.Extensions.sln +++ b/src/MongoDB.Extensions.sln @@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migration", "Migration\Migr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migration.Tests", "Migration.Tests\Migration.Tests.csproj", "{D8F246AC-65CC-4EF0-B058-08970D269B61}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Context.GuidSerializers.Tests", "Context.GuidSerializer.Tests\Context.GuidSerializers.Tests.csproj", "{2E5C44AC-9F56-462F-B0B7-25F5995F5B76}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -93,6 +95,10 @@ Global {D8F246AC-65CC-4EF0-B058-08970D269B61}.Debug|Any CPU.Build.0 = Debug|Any CPU {D8F246AC-65CC-4EF0-B058-08970D269B61}.Release|Any CPU.ActiveCfg = Release|Any CPU {D8F246AC-65CC-4EF0-B058-08970D269B61}.Release|Any CPU.Build.0 = Release|Any CPU + {2E5C44AC-9F56-462F-B0B7-25F5995F5B76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E5C44AC-9F56-462F-B0B7-25F5995F5B76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E5C44AC-9F56-462F-B0B7-25F5995F5B76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E5C44AC-9F56-462F-B0B7-25F5995F5B76}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE