diff --git a/framework/src/Volo.Abp.Mapperly/Volo/Abp/Mapperly/MapperlyAutoObjectMappingProvider.cs b/framework/src/Volo.Abp.Mapperly/Volo/Abp/Mapperly/MapperlyAutoObjectMappingProvider.cs index 4fd72ded4b..32dfa93807 100644 --- a/framework/src/Volo.Abp.Mapperly/Volo/Abp/Mapperly/MapperlyAutoObjectMappingProvider.cs +++ b/framework/src/Volo.Abp.Mapperly/Volo/Abp/Mapperly/MapperlyAutoObjectMappingProvider.cs @@ -46,7 +46,7 @@ public class MapperlyAutoObjectMappingProvider : IAutoObjectMappingProvider { mapper.BeforeMap((TSource)source); var destination = mapper.Map((TSource)source); - TryMapExtraProperties(mapper.GetType().GetSingleAttributeOrNull(), (TSource)source, destination, GetExtraProperties(destination)); + TryMapExtraProperties(mapper.GetType().GetSingleAttributeOrNull(), (TSource)source, destination, new ExtraPropertyDictionary()); mapper.AfterMap((TSource)source, destination); return destination; } @@ -56,7 +56,7 @@ public class MapperlyAutoObjectMappingProvider : IAutoObjectMappingProvider { reverseMapper.BeforeReverseMap((TSource)source); var destination = reverseMapper.ReverseMap((TSource)source); - TryMapExtraProperties(reverseMapper.GetType().GetSingleAttributeOrNull(), (TSource)source, destination, GetExtraProperties(destination)); + TryMapExtraProperties(reverseMapper.GetType().GetSingleAttributeOrNull(), (TSource)source, destination, new ExtraPropertyDictionary()); reverseMapper.AfterReverseMap((TSource)source, destination); return destination; } diff --git a/framework/test/Volo.Abp.Mapperly.Tests/Mapperly/AbpAutoMapperExtensibleDtoExtensions_Tests.cs b/framework/test/Volo.Abp.Mapperly.Tests/Mapperly/AbpAutoMapperExtensibleDtoExtensions_Tests.cs index 9e5fe4f8cf..9eca171e4e 100644 --- a/framework/test/Volo.Abp.Mapperly.Tests/Mapperly/AbpAutoMapperExtensibleDtoExtensions_Tests.cs +++ b/framework/test/Volo.Abp.Mapperly.Tests/Mapperly/AbpAutoMapperExtensibleDtoExtensions_Tests.cs @@ -40,6 +40,25 @@ public class AbpAutoMapperExtensibleDtoExtensions_Tests : AbpIntegratedTest(person); + + personDto.GetProperty("Name").ShouldBe("John"); //Defined in both classes + personDto.GetProperty("ChildCount").ShouldBe(0); //Not defined in the source, but was set to the default value by ExtensibleTestPersonDto constructor + personDto.GetProperty("CityName").ShouldBeNull(); //Ignored, but was set to the default value by ExtensibleTestPersonDto constructor + personDto.HasProperty("Age").ShouldBeFalse(); //Not defined on the destination + personDto.HasProperty("Sex").ShouldBeFalse(); //Not defined in both classes + } + [Fact] public void MapExtraProperties_Also_Should_Map_To_RegularProperties() { @@ -65,6 +84,22 @@ public class AbpAutoMapperExtensibleDtoExtensions_Tests : AbpIntegratedTest(person); + + personDto.HasProperty("Name").ShouldBe(false); + personDto.Name.ShouldBe("John"); + + personDto.HasProperty("Age").ShouldBe(false); + personDto.Age.ShouldBe(42); + } + [Fact(Skip = "Mapperly requires IHasExtraProperties.ExtraPropertyDictionary to be marked as nullable")] public void MapExtraPropertiesTo_Should_Ignored_If_ExtraProperties_Is_Null() { diff --git a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/AbpReverseMapperly_Tests.cs b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/AbpReverseMapperly_Tests.cs index 5eeebe6b82..5d166f7dc8 100644 --- a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/AbpReverseMapperly_Tests.cs +++ b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/AbpReverseMapperly_Tests.cs @@ -1,6 +1,9 @@ +using System; using Microsoft.Extensions.DependencyInjection; using Riok.Mapperly.Abstractions; using Shouldly; +using Volo.Abp.Data; +using Volo.Abp.Mapperly.SampleClasses; using Volo.Abp.ObjectMapping; using Volo.Abp.Testing; using Xunit; @@ -83,4 +86,17 @@ public class AbpReverseMapperly_Tests : AbpIntegratedTest myClass.Id.ShouldBe("2"); myClass.Name.ShouldBe("BeforeReverseMap Test2 AfterReverseMap"); } + + [Fact] + public void MapExtraProperties_Should_Filter_With_Single_Parameter_ReverseMap() + { + var dto = new ExtensibleReverseDto { Id = Guid.NewGuid() } + .SetProperty("Tag", "ok") + .SetProperty("Secret", "leaked"); + + var entity = _objectMapper.Map(dto); + + entity.GetProperty("Tag").ShouldBe("ok"); + entity.HasProperty("Secret").ShouldBeFalse(); + } } diff --git a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/ExtraProperties_Dictionary_Reference_Tests.cs b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/ExtraProperties_Dictionary_Reference_Tests.cs index e5453d09a3..6334422c09 100644 --- a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/ExtraProperties_Dictionary_Reference_Tests.cs +++ b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/ExtraProperties_Dictionary_Reference_Tests.cs @@ -101,6 +101,28 @@ public class ExtraProperties_Dictionary_Reference_Tests : AbpIntegratedTest(source); + + ReferenceEquals(source.ExtraProperties, originalSourceReference).ShouldBeTrue(); + ReferenceEquals(source.ExtraProperties, destination.ExtraProperties).ShouldBeFalse(); + + destination.ExtraProperties["TestProperty"].ShouldBe("TestValue"); + destination.ExtraProperties["NumberProperty"].ShouldBe(42); + } + [Fact] public void Should_Handle_Readonly_ExtraProperties_Gracefully() { diff --git a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/MapperlyTestModule.cs b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/MapperlyTestModule.cs index 8ff5ca2eb1..5153109472 100644 --- a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/MapperlyTestModule.cs +++ b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/MapperlyTestModule.cs @@ -1,5 +1,7 @@ -using Volo.Abp.Modularity; +using Volo.Abp.Mapperly.SampleClasses; +using Volo.Abp.Modularity; using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; namespace Volo.Abp.Mapperly; @@ -9,5 +11,17 @@ namespace Volo.Abp.Mapperly; )] public class MapperlyTestModule : AbpModule { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + public override void PreConfigureServices(ServiceConfigurationContext context) + { + OneTimeRunner.Run(() => + { + ObjectExtensionManager.Instance + .AddOrUpdateProperty("Tag") + .AddOrUpdateProperty("Secret") + .AddOrUpdateProperty("Tag") + .AddOrUpdateProperty("Secret"); + }); + } } diff --git a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/SampleClasses/MapperlyMappers.cs b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/SampleClasses/MapperlyMappers.cs index eb11d16be1..218ed36e1c 100644 --- a/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/SampleClasses/MapperlyMappers.cs +++ b/framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/SampleClasses/MapperlyMappers.cs @@ -82,4 +82,27 @@ public partial class TestEntityWithReadonlyExtraPropertiesMapper : MapperBase +{ + public override partial ExtensibleReverseDto Map(ExtensibleReverseEntity source); + + public override partial void Map(ExtensibleReverseEntity source, ExtensibleReverseDto destination); + + public override partial ExtensibleReverseEntity ReverseMap(ExtensibleReverseDto destination); + + public override partial void ReverseMap(ExtensibleReverseDto destination, ExtensibleReverseEntity source); } \ No newline at end of file