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..86fc494676 --- /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 (type.IsClass && !type.IsAbstract && 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 214872e371..25707e3899 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -13,24 +13,23 @@ namespace Volo.Abp.AutoMapper typeof(AbpObjectMappingModule), typeof(AbpObjectExtendingModule), typeof(AbpAuditingModule) - )] + )] public class AbpAutoMapperModule : AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) + public override void PreConfigureServices(ServiceConfigurationContext context) { - context.Services.AddAutoMapperObjectMapper(); - - var mapperAccessor = new MapperAccessor(); - context.Services.AddSingleton(_ => mapperAccessor); - context.Services.AddSingleton(_ => mapperAccessor); + context.Services.AddConventionalRegistrar(new AbpAutoMapperConventionalRegistrar()); } - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) { - CreateMappings(context.ServiceProvider); + context.Services.AddAutoMapperObjectMapper(); + + context.Services.AddSingleton(provider => CreateMappings(provider)); + context.Services.AddSingleton(provider => provider.GetRequiredService()); } - private void CreateMappings(IServiceProvider serviceProvider) + private MapperAccessor CreateMappings(IServiceProvider serviceProvider) { using (var scope = serviceProvider.CreateScope()) { @@ -48,7 +47,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 +58,10 @@ namespace Volo.Abp.AutoMapper ValidateAll(mapperConfiguration); - scope.ServiceProvider.GetRequiredService().Mapper = mapperConfiguration.CreateMapper(); + 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..56c5e6f061 --- /dev/null +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapper_Dependency_Injection_Tests.cs @@ -0,0 +1,62 @@ +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().ShouldNotBeNull(); + } + + [Fact] + public void Custom_MappingAction_Test() + { + var sourceModel = new SourceModel + { + Name = "Source" + }; + + _objectMapper.Map(sourceModel).Name.ShouldBe(nameof(CustomMappingActionService)); + } + + public class SourceModel + { + public string Name { get; set; } + } + + public class DestModel + { + public string Name { get; set; } + } + + public class MapperActionProfile : Profile + { + public MapperActionProfile() + { + CreateMap().AfterMap(); + } + } + + public class CustomMappingActionService : IMappingAction + { + public void Process(SourceModel source, DestModel destination, ResolutionContext context) + { + destination.Name = nameof(CustomMappingActionService); + } + } + } +}