From 20acbfc3816c57512eca1b6ab976693921df43ea Mon Sep 17 00:00:00 2001 From: Tim Holzherr Date: Mon, 2 Nov 2020 13:55:35 +0100 Subject: [PATCH] Set default value for missing nullable fields (#36) --- src/Context.Tests/ImmutableConventionTests.cs | 20 ++++++++++++++++++- ..._WithoutValueInDb_SerializeSuccessful.snap | 4 ++++ src/Context/ImmutableConvention.cs | 14 ++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 src/Context.Tests/__snapshots__/NullableReferenceTypeCase.ApplyConvention_WithoutValueInDb_SerializeSuccessful.snap diff --git a/src/Context.Tests/ImmutableConventionTests.cs b/src/Context.Tests/ImmutableConventionTests.cs index d8c775d..72d627b 100644 --- a/src/Context.Tests/ImmutableConventionTests.cs +++ b/src/Context.Tests/ImmutableConventionTests.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using MongoDB.Bson; using MongoDB.Driver; using Snapshooter.Xunit; using Squadron; @@ -6,7 +7,7 @@ namespace MongoDB.Extensions.Context.Tests { - public class ImmutableConventionTests + public class ImmutableConventionTests { public class SimpleImmutableCase : IClassFixture { @@ -104,6 +105,23 @@ public async Task ApplyConvention_WithoutValue_SerializeSuccessful() result.MatchSnapshot(); } + [Fact] + public async Task ApplyConvention_WithoutValueInDb_SerializeSuccessful() + { + // Arrange + IMongoCollection collectionTyped = + _context.Database.GetCollection("test"); + IMongoCollection collectionUntyped = + _context.Database.GetCollection("test"); + + // Act + await collectionUntyped.InsertOneAsync(new BsonDocument {{"_A", "a"}}); + + // Assert + A result = await collectionTyped.FindSync(FilterDefinition.Empty).FirstAsync(); + result.MatchSnapshot(); + } + [Fact] public async Task ApplyConvention_WithValue_SerializeSuccessful() { diff --git a/src/Context.Tests/__snapshots__/NullableReferenceTypeCase.ApplyConvention_WithoutValueInDb_SerializeSuccessful.snap b/src/Context.Tests/__snapshots__/NullableReferenceTypeCase.ApplyConvention_WithoutValueInDb_SerializeSuccessful.snap new file mode 100644 index 0000000..2f2130a --- /dev/null +++ b/src/Context.Tests/__snapshots__/NullableReferenceTypeCase.ApplyConvention_WithoutValueInDb_SerializeSuccessful.snap @@ -0,0 +1,4 @@ +{ + "_A": "a", + "_B": null +} diff --git a/src/Context/ImmutableConvention.cs b/src/Context/ImmutableConvention.cs index 1f98411..581dfd3 100644 --- a/src/Context/ImmutableConvention.cs +++ b/src/Context/ImmutableConvention.cs @@ -11,6 +11,8 @@ internal class ImmutableConvention , IClassMapConvention { private readonly BindingFlags _bindingFlags; + private readonly string _nullableAttributeFullName = + "System.Runtime.CompilerServices.NullableAttribute"; public ImmutableConvention() : this(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) @@ -35,7 +37,11 @@ public void Apply(BsonClassMap classMap) foreach (PropertyInfo property in mappingProperties) { - classMap.MapMember(property); + BsonMemberMap member = classMap.MapMember(property); + if (IsNullableProperty(property)) + { + member.SetDefaultValue((object)null); + } } if (!classMap.ClassType.IsAbstract) @@ -57,6 +63,12 @@ public void Apply(BsonClassMap classMap) } } + private bool IsNullableProperty(PropertyInfo propertyInfo) + { + return propertyInfo.CustomAttributes + .Any(a => a.AttributeType.FullName == _nullableAttributeFullName); + } + private static List GetMatchingProperties( ConstructorInfo constructor, List properties)