From 83d5b754bbb302297d55cebb68be4da78bf01ffd Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 4 Sep 2020 18:56:13 +0800 Subject: [PATCH] Create MultiLingualObjectManager --- .../AbpAutoMapperMultiLingualDtoExtensions.cs | 41 ------ .../Volo.Abp.AutoMapper.csproj | 2 - .../Abp/AutoMapper/AbpAutoMapperModule.cs | 4 +- .../IMultiLingualObjectManager.cs | 12 ++ ...nsions.cs => MultiLingualObjectManager.cs} | 41 +++--- ...toMapperMultiLingualDtoExtensions_Tests.cs | 107 -------------- .../AbpAutoMapperMultiLingualDto_Tests.cs | 132 ++++++++++++++++++ .../Abp/AutoMapper/AutoMapperTestModule.cs | 14 +- .../MultiLingualObject_Tests.cs | 91 +++++++----- 9 files changed, 227 insertions(+), 217 deletions(-) delete mode 100644 framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs create mode 100644 framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs rename framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/{MultiLingualObjectExtensions.cs => MultiLingualObjectManager.cs} (53%) delete mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs create mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs diff --git a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs deleted file mode 100644 index 273ad35645..0000000000 --- a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Volo.Abp.MultiLingualObject; -using Volo.Abp.Settings; - -namespace AutoMapper -{ - public static class AbpAutoMapperMultiLingualDtoExtensions - { - public static CreateMultiLingualMapResult MapMultiLingual( - this IMappingExpression mappingExpression, - Profile profile, - ISettingProvider provider, - bool fallbackToParentCultures = false) - where TDestination : class - where TSource : IHasMultiLingual - where TTranslation : class, IMultiLingualTranslation - { - return new CreateMultiLingualMapResult - { - TranslationMap = profile.CreateMap(), - - EntityMap = mappingExpression.BeforeMap((source, destination, context) => - { - var translation = source.GetMultiLingualTranslation(provider, fallbackToParentCultures); - - if (translation != null) - { - context.Mapper.Map(translation, destination); - } - }) - }; - } - } - - public class CreateMultiLingualMapResult - { - public IMappingExpression TranslationMap { get; set; } - - public IMappingExpression EntityMap { get; set; } - } -} diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index 124c47e055..bd5cffe848 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -16,10 +16,8 @@ - - 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 15df0d6986..214872e371 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -4,7 +4,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Auditing; using Volo.Abp.Modularity; -using Volo.Abp.MultiLingualObject; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectMapping; @@ -13,8 +12,7 @@ namespace Volo.Abp.AutoMapper [DependsOn( typeof(AbpObjectMappingModule), typeof(AbpObjectExtendingModule), - typeof(AbpAuditingModule), - typeof(AbpMultiLingualObjectModule) + typeof(AbpAuditingModule) )] public class AbpAutoMapperModule : AbpModule { diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs new file mode 100644 index 0000000000..5180588411 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.MultiLingualObject +{ + public interface IMultiLingualObjectManager + { + Task GetTranslationAsync(TMultiLingual multiLingual, + bool fallbackToParentCultures = true, string culture = null) + where TMultiLingual : IHasMultiLingual + where TTranslation : class, IMultiLingualTranslation; + } +} diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs similarity index 53% rename from framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs rename to framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs index 6212927b02..68fc083e21 100644 --- a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs @@ -2,27 +2,39 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.Settings; -using Volo.Abp.Threading; namespace Volo.Abp.MultiLingualObject { - public static class MultiLingualObjectExtensions + public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientDependency { - public static TTranslation GetMultiLingualTranslation( - this IHasMultiLingual hasMultiLingual, - ISettingProvider settingProvider, - bool fallbackToParentCultures = false) + protected ISettingProvider SettingProvider { get; } + + protected const int MaxCultureFallbackDepth = 5; + + public MultiLingualObjectManager(ISettingProvider settingProvider) + { + SettingProvider = settingProvider; + } + + public virtual async Task GetTranslationAsync(TMultiLingual multiLingual, + bool fallbackToParentCultures = true, + string culture = null) + where TMultiLingual : IHasMultiLingual where TTranslation : class, IMultiLingualTranslation { - if (hasMultiLingual.Translations == null || !hasMultiLingual.Translations.Any()) + culture ??= CultureInfo.CurrentUICulture.Name; + + if (multiLingual.Translations == null || !multiLingual.Translations.Any()) { return null; } var translation = - hasMultiLingual.Translations.FirstOrDefault(pt => pt.Language == CultureInfo.CurrentUICulture.Name); + multiLingual.Translations.FirstOrDefault(pt => pt.Language == culture); if (translation != null) { return translation; @@ -32,29 +44,26 @@ namespace Volo.Abp.MultiLingualObject { translation = GeTranslationBasedOnCulturalRecursive( - CultureInfo.CurrentUICulture.Parent, hasMultiLingual.Translations, 0); + CultureInfo.CurrentUICulture.Parent, multiLingual.Translations, 0); if (translation != null) { return translation; } } - var defaultLanguage = AsyncHelper.RunSync(() => - settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage)); + var defaultLanguage = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); - translation = hasMultiLingual.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage); + translation = multiLingual.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage); if (translation != null) { return translation; } - translation = hasMultiLingual.Translations.FirstOrDefault(); + translation = multiLingual.Translations.FirstOrDefault(); return translation; } - private const int MaxCultureFallbackDepth = 5; - - private static TTranslation GeTranslationBasedOnCulturalRecursive( + protected virtual TTranslation GeTranslationBasedOnCulturalRecursive( CultureInfo culture, ICollection translations, int currentDepth) where TTranslation : class, IMultiLingualTranslation { diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs deleted file mode 100644 index e89bf93375..0000000000 --- a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; -using Shouldly; -using Volo.Abp; -using Volo.Abp.AutoMapper; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Localization; -using Volo.Abp.MultiLingualObject.TestObjects; -using Volo.Abp.Settings; -using Volo.Abp.Testing; -using Xunit; - -namespace AutoMapper -{ - public class AbpAutoMapperMultiLingualDtoExtensions_Tests : AbpIntegratedTest - { - private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper; - private readonly MultiLingualBook _book; - - public AbpAutoMapperMultiLingualDtoExtensions_Tests() - { - _objectMapper = ServiceProvider.GetRequiredService(); - - var id = Guid.NewGuid(); - _book = new MultiLingualBook(id, 100) - { - Translations = new List - { - new MultiLingualBookTranslation - { - CoreId = id, - Language = "en", - Name = "C# in Depth" - }, - new MultiLingualBookTranslation - { - CoreId = id, - Language = "zh-Hans", - Name = "深入理解C#" - } - } - }; - } - - protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) - { - options.UseAutofac(); - } - - [Fact] - public void Should_Map_Current_UI_Culture() - { - using (CultureHelper.Use("zh-Hans")) - { - var bookDto = _objectMapper.Map(_book); - - bookDto.Name.ShouldBe("深入理解C#"); - bookDto.Price.ShouldBe(_book.Price); - bookDto.Id.ShouldBe(_book.Id); - } - } - - [Fact] - public void Should_Map_Fallback_UI_Culture() - { - using (CultureHelper.Use("en-us")) - { - var bookDto = _objectMapper.Map(_book); - - bookDto.Name.ShouldBe("C# in Depth"); - bookDto.Price.ShouldBe(_book.Price); - bookDto.Id.ShouldBe(_book.Id); - } - } - - [Fact] - public void Should_Map_Default_Language() - { - using (CultureHelper.Use("tr")) - { - var bookDto = _objectMapper.Map(_book); - - bookDto.Name.ShouldBe("C# in Depth"); - bookDto.Price.ShouldBe(_book.Price); - bookDto.Id.ShouldBe(_book.Id); - } - } - } - - public class BookProfile : Profile, ITransientDependency - { - public BookProfile() - { - } - - public BookProfile(ISettingProvider settingProvider) - { - CreateMap() - .MapMultiLingual(this, - settingProvider, true) - .TranslationMap - .ForMember(d => d.Id, m => m.MapFrom(s => s.CoreId)); - ; - } - } -} diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs new file mode 100644 index 0000000000..ea59a35ce5 --- /dev/null +++ b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp; +using Volo.Abp.AutoMapper; +using Volo.Abp.Localization; +using Volo.Abp.MultiLingualObject; +using Volo.Abp.MultiLingualObject.TestObjects; +using Volo.Abp.Testing; +using Xunit; + +namespace AutoMapper +{ + public class AbpAutoMapperMultiLingualDto_Tests : AbpIntegratedTest + { + private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper; + private readonly IMultiLingualObjectManager _multiLingualObjectManager; + private readonly MultiLingualBook _book; + + public AbpAutoMapperMultiLingualDto_Tests() + { + _multiLingualObjectManager = ServiceProvider.GetRequiredService(); + _objectMapper = ServiceProvider.GetRequiredService(); + + var id = Guid.NewGuid(); + _book = new MultiLingualBook(id, 100) + { + Translations = new List() + }; + + var en = new MultiLingualBookTranslation + { + CoreId = id, + Language = "en", + Name = "C# in Depth", + Core = _book + }; + var zh = new MultiLingualBookTranslation + { + CoreId = id, + Language = "zh-Hans", + Name = "深入理解C#", + Core = _book + }; + + _book.Translations.Add(en); + _book.Translations.Add(zh); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + [Fact] + public async Task Should_Map_Current_UI_Culture() + { + using (CultureHelper.Use("zh-Hans")) + { + var translation = + await _multiLingualObjectManager + .GetTranslationAsync(_book); + + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("深入理解C#"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Fallback_UI_Culture() + { + using (CultureHelper.Use("en-us")) + { + var translation = + await _multiLingualObjectManager + .GetTranslationAsync(_book); + + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Default_Language() + { + using (CultureHelper.Use("tr")) + { + var translation = + await _multiLingualObjectManager + .GetTranslationAsync(_book); + + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Specified_Language() + { + using (CultureHelper.Use("zh-Hans")) + { + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book, culture:"en"); + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + } + + public class BookProfile : Profile + { + public BookProfile() + { + CreateMap() + .ForMember(d => d.Price, m => m.MapFrom(s => s.Core.Price)) + .ForMember(d => d.Id, m => m.MapFrom(s => s.CoreId)); + } + } +} diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs index 6327f5dc80..6e9fb10bf2 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs @@ -1,13 +1,13 @@ -using AutoMapper; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; +using Volo.Abp.Modularity; +using Volo.Abp.MultiLingualObject; using Volo.Abp.ObjectExtending; namespace Volo.Abp.AutoMapper { [DependsOn( typeof(AbpAutoMapperModule), - typeof(AbpObjectExtendingTestModule) + typeof(AbpObjectExtendingTestModule), + typeof(AbpMultiLingualObjectModule) )] public class AutoMapperTestModule : AbpModule { @@ -16,12 +16,6 @@ namespace Volo.Abp.AutoMapper Configure(options => { options.AddMaps(); - - options.Configurators.Add(configurationContext => - { - configurationContext.MapperConfiguration.AddProfile(configurationContext.ServiceProvider - .GetService()); - }); }); } } diff --git a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs index d681520d20..f52eb17c19 100644 --- a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.MultiLingualObject.TestObjects; using Volo.Abp.ObjectMapping; -using Volo.Abp.Settings; using Volo.Abp.Testing; using Xunit; @@ -14,32 +14,38 @@ namespace Volo.Abp.MultiLingualObject { public class MultiLingualObject_Tests : AbpIntegratedTest { - private readonly IObjectMapper _objectMapper; + private readonly IObjectMapper _objectMapper; + private readonly IMultiLingualObjectManager _multiLingualObjectManager; private readonly MultiLingualBook _book; public MultiLingualObject_Tests() { - _objectMapper = ServiceProvider.GetRequiredService>(); + _objectMapper = ServiceProvider.GetRequiredService(); + _multiLingualObjectManager = ServiceProvider.GetRequiredService(); var id = Guid.NewGuid(); _book = new MultiLingualBook(id, 100) { - Translations = new List - { - new MultiLingualBookTranslation - { - CoreId = id, - Language = "en", - Name = "C# in Depth" - }, - new MultiLingualBookTranslation - { - CoreId = id, - Language = "zh-Hans", - Name = "深入理解C#" - } - } + Translations = new List() }; + + var en = new MultiLingualBookTranslation + { + CoreId = id, + Language = "en", + Name = "C# in Depth", + Core = _book + }; + var zh = new MultiLingualBookTranslation + { + CoreId = id, + Language = "zh-Hans", + Name = "深入理解C#", + Core = _book + }; + + _book.Translations.Add(en); + _book.Translations.Add(zh); } protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) @@ -48,11 +54,12 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public void Should_Map_Current_UI_Culture() + public async Task Should_Map_Current_UI_Culture() { using (CultureHelper.Use("zh-Hans")) { - var bookDto = _objectMapper.Map(_book); + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); + var bookDto = _objectMapper.Map(translation); bookDto.Name.ShouldBe("深入理解C#"); bookDto.Price.ShouldBe(_book.Price); @@ -61,11 +68,12 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public void Should_Map_Fallback_UI_Culture() + public async Task Should_Map_Fallback_UI_Culture() { using (CultureHelper.Use("en-us")) { - var bookDto = _objectMapper.Map(_book); + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); + var bookDto = _objectMapper.Map(translation); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -74,11 +82,26 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public void Should_Map_Default_Language() + public async Task Should_Map_Default_Language() { using (CultureHelper.Use("tr")) { - var bookDto = _objectMapper.Map(_book); + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Specified_Language() + { + using (CultureHelper.Use("zh-Hans")) + { + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book, culture:"en"); + var bookDto = _objectMapper.Map(translation); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -87,29 +110,21 @@ namespace Volo.Abp.MultiLingualObject } } - public class MultiLingualBookObjectMapper : IObjectMapper, + public class MultiLingualBookObjectMapper : IObjectMapper, ITransientDependency { - private readonly ISettingProvider _settingProvider; - public MultiLingualBookObjectMapper(ISettingProvider settingProvider) + public MultiLingualBookDto Map(MultiLingualBookTranslation source) { - _settingProvider = settingProvider; - } - - public MultiLingualBookDto Map(MultiLingualBook source) - { - var translation = source.GetMultiLingualTranslation(_settingProvider, true); - return new MultiLingualBookDto { - Id = source.Id, - Name = translation.Name, - Price = source.Price + Price = source.Core.Price, + Id = source.CoreId, + Name = source.Name }; } - public MultiLingualBookDto Map(MultiLingualBook source, MultiLingualBookDto destination) + public MultiLingualBookDto Map(MultiLingualBookTranslation source, MultiLingualBookDto destination) { return default; }