mirror of https://github.com/abpframework/abp.git
13 changed files with 234 additions and 130 deletions
@ -1,19 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using AutoMapper; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
public class AbpAutoMapperConfiguration : IAbpAutoMapperConfiguration |
|||
{ |
|||
public List<Action<IMapperConfigurationExpression>> Configurators { get; } |
|||
|
|||
public bool UseStaticMapper { get; set; } |
|||
|
|||
public AbpAutoMapperConfiguration() |
|||
{ |
|||
UseStaticMapper = true; |
|||
Configurators = new List<Action<IMapperConfigurationExpression>>(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,98 +1,114 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using AutoMapper; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
public class AbpAutoMapperModule : AbpModule |
|||
{ |
|||
//private readonly ITypeFinder _typeFinder;
|
|||
|
|||
//private static volatile bool _createdMappingsBefore;
|
|||
//private static readonly object SyncObj = new object();
|
|||
|
|||
//public AbpAutoMapperModule(ITypeFinder typeFinder)
|
|||
//{
|
|||
// _typeFinder = typeFinder;
|
|||
//}
|
|||
|
|||
//public override void PreInitialize()
|
|||
//{
|
|||
// IocManager.Register<IAbpAutoMapperConfiguration, AbpAutoMapperConfiguration>();
|
|||
|
|||
// Configuration.ReplaceService<ObjectMapping.IObjectMapper, AutoMapperObjectMapper>();
|
|||
|
|||
// Configuration.Modules.AbpAutoMapper().Configurators.Add(CreateCoreMappings);
|
|||
//}
|
|||
|
|||
//public override void PostInitialize()
|
|||
//{
|
|||
// CreateMappings();
|
|||
//}
|
|||
|
|||
//private void CreateMappings()
|
|||
//{
|
|||
// lock (SyncObj)
|
|||
// {
|
|||
// Action<IMapperConfigurationExpression> configurer = configuration =>
|
|||
// {
|
|||
// FindAndAutoMapTypes(configuration);
|
|||
// foreach (var configurator in Configuration.Modules.AbpAutoMapper().Configurators)
|
|||
// {
|
|||
// configurator(configuration);
|
|||
// }
|
|||
// };
|
|||
|
|||
// if (Configuration.Modules.AbpAutoMapper().UseStaticMapper)
|
|||
// {
|
|||
// //We should prevent duplicate mapping in an application, since Mapper is static.
|
|||
// if (!_createdMappingsBefore)
|
|||
// {
|
|||
// Mapper.Initialize(configurer);
|
|||
// _createdMappingsBefore = true;
|
|||
// }
|
|||
|
|||
// IocManager.IocContainer.Register(
|
|||
// Component.For<IMapper>().Instance(Mapper.Instance).LifestyleSingleton()
|
|||
// );
|
|||
// }
|
|||
// else
|
|||
// {
|
|||
// var config = new MapperConfiguration(configurer);
|
|||
// IocManager.IocContainer.Register(
|
|||
// Component.For<IMapper>().Instance(config.CreateMapper()).LifestyleSingleton()
|
|||
// );
|
|||
// }
|
|||
// }
|
|||
//}
|
|||
|
|||
//private void FindAndAutoMapTypes(IMapperConfigurationExpression configuration)
|
|||
//{
|
|||
// var types = _typeFinder.Find(type =>
|
|||
// {
|
|||
// var typeInfo = type.GetTypeInfo();
|
|||
// return typeInfo.IsDefined(typeof(AutoMapAttribute)) ||
|
|||
// typeInfo.IsDefined(typeof(AutoMapFromAttribute)) ||
|
|||
// typeInfo.IsDefined(typeof(AutoMapToAttribute));
|
|||
// }
|
|||
// );
|
|||
|
|||
// Logger<>.DebugFormat("Found {0} classes define auto mapping attributes", types.Length);
|
|||
|
|||
// foreach (var type in types)
|
|||
// {
|
|||
// Logger<>.Debug(type.FullName);
|
|||
// configuration.CreateAutoAttributeMaps(type);
|
|||
// }
|
|||
//}
|
|||
|
|||
//private void CreateCoreMappings(IMapperConfigurationExpression configuration)
|
|||
//{
|
|||
// var localizationContext = IocManager.Resolve<ILocalizationContext>();
|
|||
|
|||
// configuration.CreateMap<ILocalizableString, string>().ConvertUsing(ls => ls?.Localize(localizationContext));
|
|||
// configuration.CreateMap<LocalizableString, string>().ConvertUsing(ls => ls == null ? null : localizationContext.LocalizationManager.GetString(ls));
|
|||
//}
|
|||
private static volatile bool _createdMappingsBefore; |
|||
private static readonly object SyncObj = new object(); |
|||
|
|||
public override void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddAssemblyOf<AbpAutoMapperModule>(); |
|||
|
|||
var mapperAccessor = new MapperAccessor(); |
|||
services.AddSingleton<IMapperAccessor>(_ => mapperAccessor); |
|||
services.AddSingleton<MapperAccessor>(_ => mapperAccessor); |
|||
|
|||
services.Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
options.Configurators.Add(CreateCoreMappings); |
|||
}); |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
CreateMappings(context.ServiceProvider); |
|||
} |
|||
|
|||
private void CreateMappings(IServiceProvider serviceProvider) |
|||
{ |
|||
lock (SyncObj) |
|||
{ |
|||
using (var scope = serviceProvider.CreateScope()) |
|||
{ |
|||
var options = scope.ServiceProvider.GetRequiredService<IOptions<AbpAutoMapperOptions>>().Value; |
|||
|
|||
void ConfigureAll(IAbpAutoMapperConfigurationContext ctx) |
|||
{ |
|||
FindAndAutoMapTypes(ctx); |
|||
foreach (var configurator in options.Configurators) |
|||
{ |
|||
configurator(ctx); |
|||
} |
|||
} |
|||
|
|||
if (options.UseStaticMapper) |
|||
{ |
|||
//We should prevent duplicate mapping in an application, since Mapper is static.
|
|||
if (!_createdMappingsBefore) |
|||
{ |
|||
Mapper.Initialize(mapperConfigurationExpression => |
|||
{ |
|||
ConfigureAll(new AbpAutoMapperConfigurationContext(mapperConfigurationExpression, scope.ServiceProvider)); |
|||
}); |
|||
|
|||
_createdMappingsBefore = true; |
|||
} |
|||
|
|||
scope.ServiceProvider.GetRequiredService<MapperAccessor>().Mapper = Mapper.Instance; |
|||
} |
|||
else |
|||
{ |
|||
var config = new MapperConfiguration(mapperConfigurationExpression => |
|||
{ |
|||
ConfigureAll(new AbpAutoMapperConfigurationContext(mapperConfigurationExpression, scope.ServiceProvider)); |
|||
}); |
|||
|
|||
scope.ServiceProvider.GetRequiredService<MapperAccessor>().Mapper = config.CreateMapper(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void FindAndAutoMapTypes(IAbpAutoMapperConfigurationContext context) |
|||
{ |
|||
var typeFinder = context.ServiceProvider.GetRequiredService<ITypeFinder>(); |
|||
var logger = context.ServiceProvider.GetRequiredService<ILogger<AbpAutoMapperModule>>(); |
|||
|
|||
var types = typeFinder.Types.Where(type => |
|||
{ |
|||
var typeInfo = type.GetTypeInfo(); |
|||
return typeInfo.IsDefined(typeof(AutoMapAttribute)) || |
|||
typeInfo.IsDefined(typeof(AutoMapFromAttribute)) || |
|||
typeInfo.IsDefined(typeof(AutoMapToAttribute)); |
|||
} |
|||
).ToArray(); |
|||
|
|||
logger.LogDebug($"Found {types.Length} classes define auto mapping attributes:"); |
|||
|
|||
foreach (var type in types) |
|||
{ |
|||
logger.LogDebug(type.FullName); |
|||
context.MapperConfigurationExpression.CreateAutoAttributeMaps(type); |
|||
} |
|||
} |
|||
|
|||
private void CreateCoreMappings(IAbpAutoMapperConfigurationContext context) |
|||
{ |
|||
//Will be done when localization system completed
|
|||
//var localizationContext = IocManager.Resolve<ILocalizationContext>();
|
|||
|
|||
//configuration.CreateMap<ILocalizableString, string>().ConvertUsing(ls => ls?.Localize(localizationContext));
|
|||
//configuration.CreateMap<LocalizableString, string>().ConvertUsing(ls => ls == null ? null : localizationContext.LocalizationManager.GetString(ls));
|
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,40 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using AutoMapper; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
public class AbpAutoMapperOptions |
|||
{ |
|||
public List<Action<IAbpAutoMapperConfigurationContext>> Configurators { get; } |
|||
|
|||
public bool UseStaticMapper { get; set; } |
|||
|
|||
public AbpAutoMapperOptions() |
|||
{ |
|||
UseStaticMapper = true; |
|||
Configurators = new List<Action<IAbpAutoMapperConfigurationContext>>(); |
|||
} |
|||
} |
|||
|
|||
public interface IAbpAutoMapperConfigurationContext |
|||
{ |
|||
IMapperConfigurationExpression MapperConfigurationExpression { get; } |
|||
|
|||
IServiceProvider ServiceProvider { get; } |
|||
} |
|||
|
|||
public class AbpAutoMapperConfigurationContext : IAbpAutoMapperConfigurationContext |
|||
{ |
|||
public IMapperConfigurationExpression MapperConfigurationExpression { get; } |
|||
public IServiceProvider ServiceProvider { get; } |
|||
|
|||
public AbpAutoMapperConfigurationContext( |
|||
IMapperConfigurationExpression mapperConfigurationExpression, |
|||
IServiceProvider serviceProvider) |
|||
{ |
|||
MapperConfigurationExpression = mapperConfigurationExpression; |
|||
ServiceProvider = serviceProvider; |
|||
} |
|||
} |
|||
} |
|||
@ -1,17 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using AutoMapper; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
public interface IAbpAutoMapperConfiguration |
|||
{ |
|||
List<Action<IMapperConfigurationExpression>> Configurators { get; } |
|||
|
|||
/// <summary>
|
|||
/// Use static <see cref="Mapper.Instance"/>.
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
bool UseStaticMapper { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
public interface IMapperAccessor |
|||
{ |
|||
IMapper Mapper { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
public class MapperAccessor : IMapperAccessor |
|||
{ |
|||
public IMapper Mapper { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp1.1</TargetFramework> |
|||
<AssemblyName>Volo.Abp.AutoMapper.Tests</AssemblyName> |
|||
<PackageId>Volo.Abp.AutoMapper.Tests</PackageId> |
|||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> |
|||
<RuntimeFrameworkVersion>1.1.1</RuntimeFrameworkVersion> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,17 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.ObjectMapping; |
|||
using Volo.Abp.TestBase; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
public class AbpAutoMapperModule_Registration_Tests : AbpIntegratedTest<AutoMapperTestModule> |
|||
{ |
|||
[Fact] |
|||
public void Should_Replace_ObjectMapper() |
|||
{ |
|||
var objectMapper = ServiceProvider.GetRequiredService<IObjectMapper>(); |
|||
Assert.True(objectMapper is AutoMapperObjectMapper); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AutoMapper |
|||
{ |
|||
[DependsOn(typeof(AbpAutoMapperModule))] |
|||
public class AutoMapperTestModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddAssemblyOf<AbpAutoMapperModule>(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue