From 03551252f6c2864370373c5571309bffa31834fc Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 29 Dec 2020 15:55:34 +0800 Subject: [PATCH 1/6] DI support of AutoMapper --- .../Abp/AutoMapper/AbpAutoMapperModule.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index 214872e371..89092faed4 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -13,7 +13,7 @@ namespace Volo.Abp.AutoMapper typeof(AbpObjectMappingModule), typeof(AbpObjectExtendingModule), typeof(AbpAuditingModule) - )] + )] public class AbpAutoMapperModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) @@ -21,16 +21,11 @@ namespace Volo.Abp.AutoMapper context.Services.AddAutoMapperObjectMapper(); var mapperAccessor = new MapperAccessor(); - context.Services.AddSingleton(_ => mapperAccessor); - context.Services.AddSingleton(_ => mapperAccessor); + context.Services.AddSingleton(_ => mapperAccessor); + context.Services.Add(new ServiceDescriptor(typeof(IMapperAccessor), CreateMappings, ServiceLifetime.Singleton)); } - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - CreateMappings(context.ServiceProvider); - } - - private void CreateMappings(IServiceProvider serviceProvider) + private IMapperAccessor CreateMappings(IServiceProvider serviceProvider) { using (var scope = serviceProvider.CreateScope()) { @@ -48,7 +43,7 @@ namespace Volo.Abp.AutoMapper { foreach (var profileType in options.ValidatingProfiles) { - config.AssertConfigurationIsValid(((Profile)Activator.CreateInstance(profileType)).ProfileName); + config.AssertConfigurationIsValid(((Profile) Activator.CreateInstance(profileType)).ProfileName); } } @@ -59,7 +54,10 @@ namespace Volo.Abp.AutoMapper ValidateAll(mapperConfiguration); - scope.ServiceProvider.GetRequiredService().Mapper = mapperConfiguration.CreateMapper(); + var mapperAccessor = scope.ServiceProvider.GetRequiredService(); + mapperAccessor.Mapper = new Mapper(mapperConfiguration, serviceProvider.GetService); + + return mapperAccessor; } } } From 364732114c3e798f69d0af1bbadcfd136a474962 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 29 Dec 2020 16:46:53 +0800 Subject: [PATCH 2/6] Add AbpAutoMapperConventionalRegistrar --- .../AbpAutoMapperConventionalRegistrar.cs | 34 +++++++++++++++++++ .../Abp/AutoMapper/AbpAutoMapperModule.cs | 5 +++ 2 files changed, 39 insertions(+) create mode 100644 framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs new file mode 100644 index 0000000000..f6af2f566f --- /dev/null +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs @@ -0,0 +1,34 @@ +using System; +using System.Linq; +using AutoMapper; +using AutoMapper.Internal; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AutoMapper +{ + public class AbpAutoMapperConventionalRegistrar : ConventionalRegistrarBase + { + protected readonly Type[] OpenTypes = { + typeof(IValueResolver<,,>), + typeof(IMemberValueResolver<,,,>), + typeof(ITypeConverter<,>), + typeof(IValueConverter<,>), + typeof(IMappingAction<,>) + }; + + public override void AddType(IServiceCollection services, Type type) + { + if (IsConventionalRegistrationDisabled(type)) + { + return; + } + + if (OpenTypes.Any(type.ImplementsGenericInterface)) + { + services.TryAddTransient(type); + } + } + } +} diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index 89092faed4..479173b72d 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -16,6 +16,11 @@ namespace Volo.Abp.AutoMapper )] public class AbpAutoMapperModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddConventionalRegistrar(new AbpAutoMapperConventionalRegistrar()); + } + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAutoMapperObjectMapper(); From 82888df9bcab287246e37fc871776a5bce56d3c6 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 29 Dec 2020 16:49:03 +0800 Subject: [PATCH 3/6] Update AbpAutoMapperConventionalRegistrar --- .../Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs index f6af2f566f..86fc494676 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs @@ -25,7 +25,7 @@ namespace Volo.Abp.AutoMapper return; } - if (OpenTypes.Any(type.ImplementsGenericInterface)) + if (type.IsClass && !type.IsAbstract && OpenTypes.Any(type.ImplementsGenericInterface)) { services.TryAddTransient(type); } From 91595ee0ca0816654ec780c46bae9ba2ef055887 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 29 Dec 2020 17:51:57 +0800 Subject: [PATCH 4/6] add unit tests --- .../AutoMapper_MapperAction_Tests.cs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs new file mode 100644 index 0000000000..aa1324927a --- /dev/null +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs @@ -0,0 +1,87 @@ +using AutoMapper; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Testing; +using Xunit; +using IObjectMapper = Volo.Abp.ObjectMapping.IObjectMapper; + +namespace Volo.Abp.AutoMapper +{ + public class AutoMapper_MapperAction_Tests : AbpIntegratedTest + { + private readonly IObjectMapper _objectMapper; + + public AutoMapper_MapperAction_Tests() + { + _objectMapper = ServiceProvider.GetRequiredService(); + } + + [Fact] + public void Should_Name_DIMappingAction() + { + var mapperActionEntity = new MapperActionModel {Name = "MapperActionEntity"}; + _objectMapper.Map(mapperActionEntity) + .Name.ShouldBe(nameof(DIMappingAction)); + } + + [Fact] + public void Should_Name_NotDIMappingAction() + { + var mapperActionEntity = new MapperActionModel2 {Name = "MapperActionEntity"}; + _objectMapper.Map(mapperActionEntity) + .Name.ShouldBe(nameof(NotDIMapperAction)); + } + + public class MapperActionModel + { + public string Name { get; set; } + } + + public class MapperActionModel2 + { + public string Name { get; set; } + } + + public class MapperActionProfile : Profile + { + public MapperActionProfile() + { + CreateMap().AfterMap(); + CreateMap().AfterMap(); + } + } + + public class DIMappingAction : IMappingAction + { + private readonly MapperActionService _mapperActionService; + + public DIMappingAction(MapperActionService mapperActionService) + { + _mapperActionService = mapperActionService; + } + + public void Process(MapperActionModel source, MapperActionModel2 destination, ResolutionContext context) + { + destination.Name = _mapperActionService.GetName(); + } + } + + public class NotDIMapperAction : IMappingAction + { + public void Process(MapperActionModel2 source, MapperActionModel destination, + ResolutionContext context) + { + destination.Name = nameof(NotDIMapperAction); + } + } + + public class MapperActionService : ITransientDependency + { + public string GetName() + { + return nameof(DIMappingAction); + } + } + } +} From b6cb2860e3832ae884f87f88d4b56979266915e7 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 30 Dec 2020 20:50:11 +0800 Subject: [PATCH 5/6] Fix MapperAccessor problem. --- .../Abp/AutoMapper/AbpAutoMapperModule.cs | 15 ++- .../AutoMapper_Dependency_Injection_Tests.cs | 111 ++++++++++++++++++ .../AutoMapper_MapperAction_Tests.cs | 87 -------------- 3 files changed, 118 insertions(+), 95 deletions(-) create mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs delete mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index 479173b72d..25707e3899 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -25,12 +25,11 @@ namespace Volo.Abp.AutoMapper { context.Services.AddAutoMapperObjectMapper(); - var mapperAccessor = new MapperAccessor(); - context.Services.AddSingleton(_ => mapperAccessor); - context.Services.Add(new ServiceDescriptor(typeof(IMapperAccessor), CreateMappings, ServiceLifetime.Singleton)); + context.Services.AddSingleton(provider => CreateMappings(provider)); + context.Services.AddSingleton(provider => provider.GetRequiredService()); } - private IMapperAccessor CreateMappings(IServiceProvider serviceProvider) + private MapperAccessor CreateMappings(IServiceProvider serviceProvider) { using (var scope = serviceProvider.CreateScope()) { @@ -59,10 +58,10 @@ namespace Volo.Abp.AutoMapper ValidateAll(mapperConfiguration); - var mapperAccessor = scope.ServiceProvider.GetRequiredService(); - mapperAccessor.Mapper = new Mapper(mapperConfiguration, serviceProvider.GetService); - - return mapperAccessor; + return new MapperAccessor + { + Mapper = new Mapper(mapperConfiguration, serviceProvider.GetService) + }; } } } diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs new file mode 100644 index 0000000000..891ef0ddbb --- /dev/null +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs @@ -0,0 +1,111 @@ +using AutoMapper; +using Shouldly; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Testing; +using Xunit; +using IObjectMapper = Volo.Abp.ObjectMapping.IObjectMapper; + +namespace Volo.Abp.AutoMapper +{ + public class AutoMapper_Dependency_Injection_Tests : AbpIntegratedTest + { + private readonly IObjectMapper _objectMapper; + + public AutoMapper_Dependency_Injection_Tests() + { + _objectMapper = GetRequiredService(); + } + + [Fact] + public void Should_Registered_AutoMapper_Service() + { + GetService>().ShouldBeNull(); + GetService>().ShouldBeNull(); + GetService>().ShouldBeNull(); + GetService>().ShouldBeNull(); + GetService>().ShouldBeNull(); + } + + [Fact] + public void Custom_MappingAction_Test() + { + var sourceModel = new SourceModel + { + Name = "Source" + }; + + _objectMapper.Map(sourceModel).Name.ShouldBe(GetRequiredService().Name); + } + + public class SourceModel + { + public string Name { get; set; } + } + + public class DestModel + { + public string Name { get; set; } + } + + public class TestService : + IValueResolver, + IMemberValueResolver, + ITypeConverter, + IValueConverter, + IMappingAction + { + public string Resolve(string source, string destination, string destMember, ResolutionContext context) + { + return source; + } + + public string Resolve(string source, string destination, string sourceMember, string destMember, ResolutionContext context) + { + return source; + } + + public string Convert(string source, string destination, ResolutionContext context) + { + return source; + } + + public string Convert(string sourceMember, ResolutionContext context) + { + return sourceMember; + } + + public void Process(string source, string destination, ResolutionContext context) + { + + } + } + + public class MapperActionProfile : Profile + { + public MapperActionProfile() + { + CreateMap().AfterMap(); + } + } + + public class CustomMappingAction : IMappingAction + { + private readonly TestNameService _testNameService; + + public CustomMappingAction(TestNameService testNameService) + { + _testNameService = testNameService; + } + + public void Process(SourceModel source, DestModel destination, ResolutionContext context) + { + destination.Name = _testNameService.Name; + } + } + + public class TestNameService : ITransientDependency + { + public string Name => nameof(TestNameService); + } + } +} diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs deleted file mode 100644 index aa1324927a..0000000000 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_MapperAction_Tests.cs +++ /dev/null @@ -1,87 +0,0 @@ -using AutoMapper; -using Microsoft.Extensions.DependencyInjection; -using Shouldly; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Testing; -using Xunit; -using IObjectMapper = Volo.Abp.ObjectMapping.IObjectMapper; - -namespace Volo.Abp.AutoMapper -{ - public class AutoMapper_MapperAction_Tests : AbpIntegratedTest - { - private readonly IObjectMapper _objectMapper; - - public AutoMapper_MapperAction_Tests() - { - _objectMapper = ServiceProvider.GetRequiredService(); - } - - [Fact] - public void Should_Name_DIMappingAction() - { - var mapperActionEntity = new MapperActionModel {Name = "MapperActionEntity"}; - _objectMapper.Map(mapperActionEntity) - .Name.ShouldBe(nameof(DIMappingAction)); - } - - [Fact] - public void Should_Name_NotDIMappingAction() - { - var mapperActionEntity = new MapperActionModel2 {Name = "MapperActionEntity"}; - _objectMapper.Map(mapperActionEntity) - .Name.ShouldBe(nameof(NotDIMapperAction)); - } - - public class MapperActionModel - { - public string Name { get; set; } - } - - public class MapperActionModel2 - { - public string Name { get; set; } - } - - public class MapperActionProfile : Profile - { - public MapperActionProfile() - { - CreateMap().AfterMap(); - CreateMap().AfterMap(); - } - } - - public class DIMappingAction : IMappingAction - { - private readonly MapperActionService _mapperActionService; - - public DIMappingAction(MapperActionService mapperActionService) - { - _mapperActionService = mapperActionService; - } - - public void Process(MapperActionModel source, MapperActionModel2 destination, ResolutionContext context) - { - destination.Name = _mapperActionService.GetName(); - } - } - - public class NotDIMapperAction : IMappingAction - { - public void Process(MapperActionModel2 source, MapperActionModel destination, - ResolutionContext context) - { - destination.Name = nameof(NotDIMapperAction); - } - } - - public class MapperActionService : ITransientDependency - { - public string GetName() - { - return nameof(DIMappingAction); - } - } - } -} From b8bc6973110c9bac81c05893cc456caef7670f88 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 30 Dec 2020 21:32:58 +0800 Subject: [PATCH 6/6] Fix Should_Registered_AutoMapper_Service test method. --- .../AutoMapper_Dependency_Injection_Tests.cs | 59 ++----------------- 1 file changed, 5 insertions(+), 54 deletions(-) diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs index 891ef0ddbb..56c5e6f061 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs @@ -19,11 +19,7 @@ namespace Volo.Abp.AutoMapper [Fact] public void Should_Registered_AutoMapper_Service() { - GetService>().ShouldBeNull(); - GetService>().ShouldBeNull(); - GetService>().ShouldBeNull(); - GetService>().ShouldBeNull(); - GetService>().ShouldBeNull(); + GetService().ShouldNotBeNull(); } [Fact] @@ -34,7 +30,7 @@ namespace Volo.Abp.AutoMapper Name = "Source" }; - _objectMapper.Map(sourceModel).Name.ShouldBe(GetRequiredService().Name); + _objectMapper.Map(sourceModel).Name.ShouldBe(nameof(CustomMappingActionService)); } public class SourceModel @@ -47,65 +43,20 @@ namespace Volo.Abp.AutoMapper public string Name { get; set; } } - public class TestService : - IValueResolver, - IMemberValueResolver, - ITypeConverter, - IValueConverter, - IMappingAction - { - public string Resolve(string source, string destination, string destMember, ResolutionContext context) - { - return source; - } - - public string Resolve(string source, string destination, string sourceMember, string destMember, ResolutionContext context) - { - return source; - } - - public string Convert(string source, string destination, ResolutionContext context) - { - return source; - } - - public string Convert(string sourceMember, ResolutionContext context) - { - return sourceMember; - } - - public void Process(string source, string destination, ResolutionContext context) - { - - } - } - public class MapperActionProfile : Profile { public MapperActionProfile() { - CreateMap().AfterMap(); + CreateMap().AfterMap(); } } - public class CustomMappingAction : IMappingAction + public class CustomMappingActionService : IMappingAction { - private readonly TestNameService _testNameService; - - public CustomMappingAction(TestNameService testNameService) - { - _testNameService = testNameService; - } - public void Process(SourceModel source, DestModel destination, ResolutionContext context) { - destination.Name = _testNameService.Name; + destination.Name = nameof(CustomMappingActionService); } } - - public class TestNameService : ITransientDependency - { - public string Name => nameof(TestNameService); - } } }