diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index de41f864c7..534b7c6d92 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -248,6 +248,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MailKit", "src\Vol EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MailKit.Tests", "test\Volo.Abp.MailKit.Tests\Volo.Abp.MailKit.Tests.csproj", "{70DD6E17-B98B-4B00-8F38-C489E291BB53}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.ObjectMapping.Tests", "test\Volo.Abp.ObjectMapping.Tests\Volo.Abp.ObjectMapping.Tests.csproj", "{667F5544-C1EB-447C-96FD-9B757F04DE2B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -738,6 +740,10 @@ Global {70DD6E17-B98B-4B00-8F38-C489E291BB53}.Debug|Any CPU.Build.0 = Debug|Any CPU {70DD6E17-B98B-4B00-8F38-C489E291BB53}.Release|Any CPU.ActiveCfg = Release|Any CPU {70DD6E17-B98B-4B00-8F38-C489E291BB53}.Release|Any CPU.Build.0 = Release|Any CPU + {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -864,6 +870,7 @@ Global {E026A085-D881-4AE0-9F08-422AC3903BD7} = {447C8A77-E5F0-4538-8687-7383196D04EA} {0CAED4CC-1CFD-4092-A326-AFE4DB3A9AB4} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {70DD6E17-B98B-4B00-8F38-C489E291BB53} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {667F5544-C1EB-447C-96FD-9B757F04DE2B} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs index 62258329ad..8d62a4e188 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs @@ -24,7 +24,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages { public IServiceProvider ServiceProvider { get; set; } protected readonly object ServiceProviderLock = new object(); + protected TService LazyGetRequiredService(ref TService reference) + => LazyGetRequiredService(typeof(TService), ref reference); + + protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) { if (reference == null) { @@ -32,7 +36,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages { if (reference == null) { - reference = ServiceProvider.GetRequiredService(); + reference = (TRef)ServiceProvider.GetRequiredService(serviceType); } } } @@ -48,7 +52,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); private IUnitOfWorkManager _unitOfWorkManager; - public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + protected Type ObjectMapperContext { get; set; } + public IObjectMapper ObjectMapper + { + get + { + if (_objectMapper != null) + { + return _objectMapper; + } + + if (ObjectMapperContext == null) + { + return LazyGetRequiredService(ref _objectMapper); + } + + return LazyGetRequiredService( + typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext), + ref _objectMapper + ); + } + } private IObjectMapper _objectMapper; public IGuidGenerator GuidGenerator => LazyGetRequiredService(ref _guidGenerator); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs index 943d0d6e3f..c3e5c61f36 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs @@ -23,7 +23,11 @@ namespace Volo.Abp.AspNetCore.Mvc { public IServiceProvider ServiceProvider { get; set; } protected readonly object ServiceProviderLock = new object(); + protected TService LazyGetRequiredService(ref TService reference) + => LazyGetRequiredService(typeof(TService), ref reference); + + protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) { if (reference == null) { @@ -31,7 +35,7 @@ namespace Volo.Abp.AspNetCore.Mvc { if (reference == null) { - reference = ServiceProvider.GetRequiredService(); + reference = (TRef)ServiceProvider.GetRequiredService(serviceType); } } } @@ -42,7 +46,27 @@ namespace Volo.Abp.AspNetCore.Mvc public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); private IUnitOfWorkManager _unitOfWorkManager; - public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + protected Type ObjectMapperContext { get; set; } + public IObjectMapper ObjectMapper + { + get + { + if (_objectMapper != null) + { + return _objectMapper; + } + + if (ObjectMapperContext == null) + { + return LazyGetRequiredService(ref _objectMapper); + } + + return LazyGetRequiredService( + typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext), + ref _objectMapper + ); + } + } private IObjectMapper _objectMapper; public IGuidGenerator GuidGenerator => LazyGetRequiredService(ref _guidGenerator); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs index 883fea8046..e29cb5fbef 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs @@ -1,15 +1,55 @@ -using Microsoft.AspNetCore.Mvc; +using System; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.ObjectMapping; namespace Volo.Abp.AspNetCore.Mvc { public abstract class AbpViewComponent : ViewComponent { - public IObjectMapper ObjectMapper { get; set; } + public IServiceProvider ServiceProvider { get; set; } + protected readonly object ServiceProviderLock = new object(); - protected AbpViewComponent() + protected TService LazyGetRequiredService(ref TService reference) + => LazyGetRequiredService(typeof(TService), ref reference); + + protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) { - + if (reference == null) + { + lock (ServiceProviderLock) + { + if (reference == null) + { + reference = (TRef)ServiceProvider.GetRequiredService(serviceType); + } + } + } + + return reference; + } + + protected Type ObjectMapperContext { get; set; } + public IObjectMapper ObjectMapper + { + get + { + if (_objectMapper != null) + { + return _objectMapper; + } + + if (ObjectMapperContext == null) + { + return LazyGetRequiredService(ref _objectMapper); + } + + return LazyGetRequiredService( + typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext), + ref _objectMapper + ); + } } + private IObjectMapper _objectMapper; } } diff --git a/framework/src/Volo.Abp.AutoMapper/Microsoft/Extensions/DependencyInjection/AbpAutoMapperServiceCollectionExtensions.cs b/framework/src/Volo.Abp.AutoMapper/Microsoft/Extensions/DependencyInjection/AbpAutoMapperServiceCollectionExtensions.cs new file mode 100644 index 0000000000..c3e909486b --- /dev/null +++ b/framework/src/Volo.Abp.AutoMapper/Microsoft/Extensions/DependencyInjection/AbpAutoMapperServiceCollectionExtensions.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.AutoMapper; +using Volo.Abp.ObjectMapping; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AbpAutoMapperServiceCollectionExtensions + { + public static IServiceCollection AddAutoMapperObjectMapper(this IServiceCollection services) + { + return services.Replace( + ServiceDescriptor.Transient() + ); + } + + public static IServiceCollection AddAutoMapperObjectMapper(this IServiceCollection services) + { + return services.Replace( + ServiceDescriptor.Transient, AutoMapperAutoObjectMappingProvider>() + ); + } + } +} 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 ebf517dc65..ba3ef2ada8 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -12,6 +12,8 @@ namespace Volo.Abp.AutoMapper { public override void ConfigureServices(ServiceConfigurationContext context) { + context.Services.AddAutoMapperObjectMapper(); + var mapperAccessor = new MapperAccessor(); context.Services.AddSingleton(_ => mapperAccessor); context.Services.AddSingleton(_ => mapperAccessor); diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperAutoObjectMappingProvider.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperAutoObjectMappingProvider.cs index 7dc33fb011..ca5b7c0ea1 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperAutoObjectMappingProvider.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperAutoObjectMappingProvider.cs @@ -1,13 +1,18 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.DependencyInjection; -using Volo.Abp.ObjectMapping; +using Volo.Abp.ObjectMapping; namespace Volo.Abp.AutoMapper { - [Dependency(ServiceLifetime.Transient, ReplaceServices = true)] + public class AutoMapperAutoObjectMappingProvider : AutoMapperAutoObjectMappingProvider, IAutoObjectMappingProvider + { + public AutoMapperAutoObjectMappingProvider(IMapperAccessor mapperAccessor) + : base(mapperAccessor) + { + } + } + public class AutoMapperAutoObjectMappingProvider : IAutoObjectMappingProvider { - protected IMapperAccessor MapperAccessor { get; } + public IMapperAccessor MapperAccessor { get; } public AutoMapperAutoObjectMappingProvider(IMapperAccessor mapperAccessor) { diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/ObjectMapping/AbpAutoMapperObjectMapperExtensions.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/ObjectMapping/AbpAutoMapperObjectMapperExtensions.cs new file mode 100644 index 0000000000..7e4e91751f --- /dev/null +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/ObjectMapping/AbpAutoMapperObjectMapperExtensions.cs @@ -0,0 +1,23 @@ +using AutoMapper; +using Volo.Abp.AutoMapper; + +namespace Volo.Abp.ObjectMapping +{ + public static class AbpAutoMapperObjectMapperExtensions + { + public static IMapper GetMapper(this IObjectMapper objectMapper) + { + return objectMapper.AutoObjectMappingProvider.GetMapper(); + } + + public static IMapper GetMapper(this IAutoObjectMappingProvider autoObjectMappingProvider) + { + if (autoObjectMappingProvider is AutoMapperAutoObjectMappingProvider autoMapperAutoObjectMappingProvider) + { + return autoMapperAutoObjectMappingProvider.MapperAccessor.Mapper; + } + + throw new AbpException($"Given object is not an instance of {typeof(AutoMapperAutoObjectMappingProvider).AssemblyQualifiedName}. The type of the given object it {autoObjectMappingProvider.GetType().AssemblyQualifiedName}"); + } + } +} diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs index 698f2c0ea3..0de23c826b 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs @@ -34,7 +34,11 @@ namespace Volo.Abp.Application.Services { public IServiceProvider ServiceProvider { get; set; } protected readonly object ServiceProviderLock = new object(); + protected TService LazyGetRequiredService(ref TService reference) + => LazyGetRequiredService(typeof(TService), ref reference); + + protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) { if (reference == null) { @@ -42,7 +46,7 @@ namespace Volo.Abp.Application.Services { if (reference == null) { - reference = ServiceProvider.GetRequiredService(); + reference = (TRef)ServiceProvider.GetRequiredService(serviceType); } } } @@ -57,7 +61,27 @@ namespace Volo.Abp.Application.Services public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); private IUnitOfWorkManager _unitOfWorkManager; - public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + protected Type ObjectMapperContext { get; set; } + public IObjectMapper ObjectMapper + { + get + { + if (_objectMapper != null) + { + return _objectMapper; + } + + if (ObjectMapperContext == null) + { + return LazyGetRequiredService(ref _objectMapper); + } + + return LazyGetRequiredService( + typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext), + ref _objectMapper + ); + } + } private IObjectMapper _objectMapper; public IGuidGenerator GuidGenerator { get; set; } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs index c8e89f6869..237e89aa53 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs @@ -188,8 +188,7 @@ namespace Volo.Abp.Application.Services protected virtual IQueryable ApplySorting(IQueryable query, TGetListInput input) { //Try to sort query if available - var sortInput = input as ISortedResultRequest; - if (sortInput != null) + if (input is ISortedResultRequest sortInput) { if (!sortInput.Sorting.IsNullOrWhiteSpace()) { @@ -215,15 +214,13 @@ namespace Volo.Abp.Application.Services protected virtual IQueryable ApplyPaging(IQueryable query, TGetListInput input) { //Try to use paging if available - var pagedInput = input as IPagedResultRequest; - if (pagedInput != null) + if (input is IPagedResultRequest pagedInput) { return query.PageBy(pagedInput); } //Try to limit query result if available - var limitedInput = input as ILimitedResultRequest; - if (limitedInput != null) + if (input is ILimitedResultRequest limitedInput) { return query.Take(limitedInput.MaxResultCount); } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs index 5b386599ef..b15ea3d6a4 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Options; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; using Volo.Abp.EventBus.Distributed; @@ -9,14 +10,14 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed { public class EntityToEtoMapper : IEntityToEtoMapper, ITransientDependency { - protected IObjectMapper ObjectMapper { get; } + protected IHybridServiceScopeFactory HybridServiceScopeFactory { get; } protected DistributedEventBusOptions Options { get; } public EntityToEtoMapper( IOptions options, - IObjectMapper objectMapper) + IHybridServiceScopeFactory hybridServiceScopeFactory) { - ObjectMapper = objectMapper; + HybridServiceScopeFactory = hybridServiceScopeFactory; Options = options.Value; } @@ -31,15 +32,23 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed } var entityType = ProxyHelper.UnProxy(entity).GetType(); - var etoType = Options.EtoMappings.GetOrDefault(entityType); - if (etoType == null) + var etoMappingItem = Options.EtoMappings.GetOrDefault(entityType); + if (etoMappingItem == null) { var keys = entity.GetKeys().JoinAsString(","); return new EntityEto(entityType.FullName, keys); } - //TODO: Also add KeysAsString property to resulting json for compatibility with the EntityEto! - return ObjectMapper.Map(entityType, etoType, entityObj); + using (var scope = HybridServiceScopeFactory.CreateScope()) + { + var objectMapperType = etoMappingItem.ObjectMappingContextType == null + ? typeof(IObjectMapper) + : typeof(IObjectMapper<>).MakeGenericType(etoMappingItem.ObjectMappingContextType); + + var objectMapper = (IObjectMapper) scope.ServiceProvider.GetRequiredService(objectMapperType); + + return objectMapper.Map(entityType, etoMappingItem.EtoType, entityObj); + } } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs index b9bcd3ed8b..aae99d0cb7 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; namespace Volo.Abp.EventBus.Distributed { - public class EtoMappingDictionary : Dictionary + public class EtoMappingDictionary : Dictionary { - public void Add() + public void Add(Type objectMappingContextType = null) { - this[typeof(TEntity)] = typeof(TEntityEto); + this[typeof(TEntity)] = new EtoMappingDictionaryItem(typeof(TEntityEto), objectMappingContextType); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionaryItem.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionaryItem.cs new file mode 100644 index 0000000000..d634c44b4d --- /dev/null +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionaryItem.cs @@ -0,0 +1,17 @@ +using System; + +namespace Volo.Abp.EventBus.Distributed +{ + public class EtoMappingDictionaryItem + { + public Type EtoType { get; } + + public Type ObjectMappingContextType { get; } + + public EtoMappingDictionaryItem(Type etoType, Type objectMappingContextType = null) + { + EtoType = etoType; + ObjectMappingContextType = objectMappingContextType; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs index 7fb7b039a7..1d7e026589 100644 --- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs +++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs @@ -19,5 +19,13 @@ namespace Volo.Abp.ObjectMapping ); }); } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddTransient( + typeof(IObjectMapper<>), + typeof(DefaultObjectMapper<>) + ); + } } } diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs index d4295e20d7..dbc0dc6f3a 100644 --- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs +++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs @@ -4,11 +4,22 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.ObjectMapping { - //TODO: It can be slow to always check if service is available. Test it and optimize if necessary. + public class DefaultObjectMapper : DefaultObjectMapper, IObjectMapper + { + public DefaultObjectMapper( + IServiceProvider serviceProvider, + IAutoObjectMappingProvider autoObjectMappingProvider + ) : base( + serviceProvider, + autoObjectMappingProvider) + { + + } + } public class DefaultObjectMapper : IObjectMapper, ITransientDependency { - protected IAutoObjectMappingProvider AutoObjectMappingProvider { get; } + public IAutoObjectMappingProvider AutoObjectMappingProvider { get; } protected IServiceProvider ServiceProvider { get; } public DefaultObjectMapper( @@ -18,6 +29,8 @@ namespace Volo.Abp.ObjectMapping AutoObjectMappingProvider = autoObjectMappingProvider; ServiceProvider = serviceProvider; } + + //TODO: It can be slow to always check if service is available. Test it and optimize if necessary. public virtual TDestination Map(TSource source) { diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IAutoObjectMappingProvider.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IAutoObjectMappingProvider.cs index 37ac1d0b7b..b402d223f0 100644 --- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IAutoObjectMappingProvider.cs +++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IAutoObjectMappingProvider.cs @@ -6,4 +6,9 @@ namespace Volo.Abp.ObjectMapping TDestination Map(TSource source, TDestination destination); } + + public interface IAutoObjectMappingProvider : IAutoObjectMappingProvider + { + + } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs index 88ee14d707..522ba44e34 100644 --- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs +++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs @@ -5,6 +5,11 @@ /// public interface IObjectMapper { + /// + /// Gets the underlying object that is used for auto object mapping. + /// + IAutoObjectMappingProvider AutoObjectMappingProvider { get; } + /// /// Converts an object to another. Creates a new object of . /// @@ -24,6 +29,14 @@ TDestination Map(TSource source, TDestination destination); } + /// + /// Defines a simple interface to automatically map objects for a specific context. + /// + public interface IObjectMapper : IObjectMapper + { + + } + /// /// Maps an object to another. /// Implement this interface to override object to object mapping for specific types. diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs index a5051447b4..436c0402d8 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs @@ -22,6 +22,13 @@ namespace Volo.Abp.AutoMapper Assert.True(ServiceProvider.GetRequiredService() is AutoMapperAutoObjectMappingProvider); } + [Fact] + public void Should_Get_Internal_Mapper() + { + _objectMapper.GetMapper().ShouldNotBeNull(); + _objectMapper.AutoObjectMappingProvider.GetMapper().ShouldNotBeNull(); + } + [Fact] public void Should_Map_Objects_With_AutoMap_Attributes() { diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.csproj b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.csproj new file mode 100644 index 0000000000..7af0ec54b6 --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + netcoreapp3.0 + + + + + + + + + + diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestBase.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestBase.cs new file mode 100644 index 0000000000..9ba65b5a10 --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestBase.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.ObjectMapping +{ + public abstract class AbpObjectMappingTestBase : AbpIntegratedTest + { + + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestModule.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestModule.cs new file mode 100644 index 0000000000..90b6943412 --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestModule.cs @@ -0,0 +1,17 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.ObjectMapping +{ + [DependsOn( + typeof(AbpObjectMappingModule), + typeof(AbpTestBaseModule) + )] + public class AbpObjectMappingTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddTest1AutoObjectMappingProvider(); + context.Services.AddTest2AutoObjectMappingProvider(); + } + } +} diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ContextSpecificMapper_Tests.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ContextSpecificMapper_Tests.cs new file mode 100644 index 0000000000..e24dd9a15e --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ContextSpecificMapper_Tests.cs @@ -0,0 +1,24 @@ +using Shouldly; +using Xunit; + +namespace Volo.Abp.ObjectMapping +{ + public class ContextSpecificMapper_Tests : AbpObjectMappingTestBase + { + [Fact] + public void Should_Resolve_Correct_ObjectMappper_For_Specific_Context() + { + GetRequiredService>() + .ShouldBeOfType(typeof(DefaultObjectMapper)); + + GetRequiredService>() + .ShouldBeOfType(typeof(Test1AutoObjectMappingProvider)); + + GetRequiredService>() + .ShouldBeOfType(typeof(DefaultObjectMapper)); + + GetRequiredService>() + .ShouldBeOfType(typeof(Test2AutoObjectMappingProvider)); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext1.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext1.cs new file mode 100644 index 0000000000..96fcb94686 --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext1.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.ObjectMapping +{ + public class MappingContext1 + { + + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext2.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext2.cs new file mode 100644 index 0000000000..131a9a268b --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext2.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.ObjectMapping +{ + public class MappingContext2 + { + + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test1AutoObjectMappingProvider.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test1AutoObjectMappingProvider.cs new file mode 100644 index 0000000000..b96df71aed --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test1AutoObjectMappingProvider.cs @@ -0,0 +1,22 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.ObjectMapping +{ + public class Test1AutoObjectMappingProvider : Test1AutoObjectMappingProvider, IAutoObjectMappingProvider + { + + } + + public class Test1AutoObjectMappingProvider : IAutoObjectMappingProvider, ITransientDependency + { + public TDestination Map(object source) + { + return default; + } + + public TDestination Map(TSource source, TDestination destination) + { + return default; + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test2AutoObjectMappingProvider.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test2AutoObjectMappingProvider.cs new file mode 100644 index 0000000000..3ac0792570 --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test2AutoObjectMappingProvider.cs @@ -0,0 +1,15 @@ +namespace Volo.Abp.ObjectMapping +{ + public class Test2AutoObjectMappingProvider : IAutoObjectMappingProvider + { + public TDestination Map(object source) + { + return default; + } + + public TDestination Map(TSource source, TDestination destination) + { + return default; + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/TestContextRegistrar.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/TestContextRegistrar.cs new file mode 100644 index 0000000000..b7568fc15e --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/TestContextRegistrar.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.ObjectMapping +{ + public static class TestContextRegistrar + { + public static IServiceCollection AddTest1AutoObjectMappingProvider(this IServiceCollection services) + { + return services + .AddTransient< + IAutoObjectMappingProvider, + Test1AutoObjectMappingProvider + >(); + } + + public static IServiceCollection AddTest2AutoObjectMappingProvider(this IServiceCollection services) + { + return services + .AddTransient< + IAutoObjectMappingProvider, + Test2AutoObjectMappingProvider + >(); + } + } +} \ No newline at end of file