diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs index 83093e0370..d15870e7c1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs @@ -9,6 +9,5 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending public Dictionary Properties { get; set; } public Dictionary Configuration { get; set; } - } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs new file mode 100644 index 0000000000..4f2dc526eb --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +{ + [Serializable] + public class ExtensionEnumDto + { + public List Fields { get; set; } + + public string LocalizationResource { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs new file mode 100644 index 0000000000..ddc7c349d4 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs @@ -0,0 +1,12 @@ +using System; + +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +{ + [Serializable] + public class ExtensionEnumFieldDto + { + public string Name { get; set; } + + public object Value { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs index fd9665eab1..0338bbd4dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs @@ -7,5 +7,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending public class ObjectExtensionsDto { public Dictionary Modules { get; set; } + + public Dictionary Enums { get; set; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index bb79740a41..21f6c498a9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Linq.Dynamic.Core; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Rendering; @@ -12,6 +13,7 @@ using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; using Volo.Abp.DynamicProxy; +using Volo.Abp.Localization; using Volo.Abp.Reflection; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form @@ -21,12 +23,18 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form private readonly IHtmlGenerator _generator; private readonly HtmlEncoder _encoder; private readonly IAbpTagHelperLocalizer _tagHelperLocalizer; + private readonly IStringLocalizerFactory _stringLocalizerFactory; - public AbpSelectTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder, IAbpTagHelperLocalizer tagHelperLocalizer) + public AbpSelectTagHelperService( + IHtmlGenerator generator, + HtmlEncoder encoder, + IAbpTagHelperLocalizer tagHelperLocalizer, + IStringLocalizerFactory stringLocalizerFactory) { _generator = generator; _encoder = encoder; _tagHelperLocalizer = tagHelperLocalizer; + _stringLocalizerFactory = stringLocalizerFactory; } public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) @@ -209,74 +217,33 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form } var containerLocalizer = _tagHelperLocalizer.GetLocalizerOrNull(explorer.Container.ModelType.Assembly); - IStringLocalizer modelObjectLocalizer = null; - if (explorer.Model != null) - { - modelObjectLocalizer = _tagHelperLocalizer.GetLocalizerOrNull(ProxyHelper.UnProxy(explorer.Model).GetType().Assembly); - } - - selectItems.AddRange(enumType.GetEnumNames() - .Select(enumName => new SelectListItem - { - Value = Convert.ToUInt64(Enum.Parse(enumType, enumName)).ToString(), - Text = GetLocalizedEnumFieldName(containerLocalizer, modelObjectLocalizer, enumType, enumName) - })); - - return selectItems; - } - - protected virtual string GetLocalizedEnumFieldName( - IStringLocalizer containerLocalizer, - IStringLocalizer modelObjectLocalizer, - Type enumType, - string fieldName) - { - LocalizedString localizedString; - - //Look for the enum name + enum field name - - var localizationKey = enumType.Name + "." + fieldName; - if (containerLocalizer != null) - { - localizedString = containerLocalizer[localizationKey]; - if (!localizedString.ResourceNotFound) - { - return localizedString.Value; - } - } - if (modelObjectLocalizer != null) + foreach (var enumValue in enumType.GetEnumValues()) { - localizedString = modelObjectLocalizer[localizationKey]; - if (!localizedString.ResourceNotFound) + var memberName = enumType.GetEnumName(enumValue); + var localizedMemberName = AbpInternalLocalizationHelper.LocalizeWithFallback( + new[] + { + containerLocalizer, + _stringLocalizerFactory.CreateDefaultOrNull() + }, + new[] + { + $"Enum:{enumType.Name}.{memberName}", + $"{enumType.Name}.{memberName}", + memberName + }, + memberName + ); + + selectItems.Add(new SelectListItem { - return localizedString.Value; - } - } - - //Look for the enum field name - - localizationKey = fieldName; - - if (containerLocalizer != null) - { - localizedString = containerLocalizer[localizationKey]; - if (!localizedString.ResourceNotFound) - { - return localizedString.Value; - } - } - - if (modelObjectLocalizer != null) - { - localizedString = modelObjectLocalizer[localizationKey]; - if (!localizedString.ResourceNotFound) - { - return localizedString.Value; - } + Value = enumValue.ToString(), + Text = localizedMemberName + }); } - return fieldName; + return selectItems; } protected virtual List GetSelectItemsFromAttribute( diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js index 9ee545615c..dbf73618ad 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js @@ -99,6 +99,26 @@ function initializeObjectExtensions() { + var getShortEnumTypeName = function (enumType) { + var lastDotIndex = enumType.lastIndexOf('.'); + if (lastDotIndex < 0) { + return enumType; + } + + return enumType.substr(lastDotIndex + 1); + }; + + var getEnumMemberName = function (enumInfo, enumMemberValue) { + for (var i = 0; i < enumInfo.fields.length; i++) { + var enumField = enumInfo.fields[i]; + if (enumField.value == enumMemberValue) { + return enumField.name; + } + } + + return null; + }; + function localizeDisplayName(propertyName, displayName) { if (displayName && displayName.name) { return abp.localization.localize(displayName.name, displayName.resource); @@ -111,6 +131,48 @@ return abp.localization.localize(propertyName); } + function localizeWithFallback(localizationResources, keys, defaultValue) { + for (var i = 0; i < localizationResources.length; i++) { + var localizationResource = localizationResources[i]; + if (!localizationResource) { + continue; + } + + for (var j = 0; j < keys.length; j++) { + var key = keys[j]; + + if (abp.localization.isLocalized(key, localizationResource)) { + return abp.localization.localize(key, localizationResource); + } + } + } + + return defaultValue; + } + + function localizeEnumMember(property, row) { + var enumType = property.config.type; + var enumInfo = abp.objectExtensions.enums[enumType]; + var enumMemberValue = row.extraProperties[property.name]; + var enumMemberName = getEnumMemberName(enumInfo, enumMemberValue); + + if (!enumMemberName) { + return enumMemberValue; + } + + var shortEnumType = getShortEnumTypeName(enumType); + + return localizeWithFallback( + [enumInfo.localizationResource, abp.localization.defaultResourceName], + [ + 'Enum:' + shortEnumType + '.' + enumMemberName, + shortEnumType + '.' + enumMemberName, + enumMemberName + ], + enumMemberName + ); + } + function configureTableColumns(tableName, columnConfigs) { abp.ui.extensions.tableColumns.get(tableName) .addContributor( @@ -137,16 +199,30 @@ return tableProperties; } + function convertPropertyToColumnConfig(property) { + var columnConfig = { + title: localizeDisplayName(property.name, property.config.displayName), + data: "extraProperties." + property.name, + orderable: false + }; + + if (property.config.typeSimple === 'enum') { + columnConfig.render = function (data, type, row) { + return localizeEnumMember( + property, + row + ); + } + } + + return columnConfig; + } + function convertPropertiesToColumnConfigs(properties) { var columnConfigs = []; for (var i = 0; i < properties.length; i++) { - var tableProperty = properties[i]; - columnConfigs.push({ - title: localizeDisplayName(tableProperty.name, tableProperty.config.displayName), - data: "extraProperties." + tableProperty.name, - orderable: false - }); + columnConfigs.push(convertPropertyToColumnConfig(properties[i])); } return columnConfigs; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs index aab28b3cb9..870ff0368e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs @@ -39,7 +39,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending { var objectExtensionsDto = new ObjectExtensionsDto { - Modules = new Dictionary() + Modules = new Dictionary(), + Enums = new Dictionary() }; foreach (var moduleConfig in ObjectExtensionManager.Instance.Modules()) @@ -47,6 +48,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending objectExtensionsDto.Modules[moduleConfig.Key] = CreateModuleExtensionDto(moduleConfig.Value); } + FillEnums(objectExtensionsDto); + return objectExtensionsDto; } @@ -183,5 +186,45 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending return null; } + + protected virtual void FillEnums(ObjectExtensionsDto objectExtensionsDto) + { + var enumProperties = ObjectExtensionManager.Instance.Modules().Values + .SelectMany( + m => m.Entities.Values.SelectMany( + e => e.GetProperties() + ) + ) + .Where(p => p.Type.IsEnum) + .ToList(); + + foreach (var enumProperty in enumProperties) + { + // ReSharper disable once AssignNullToNotNullAttribute (enumProperty.Type.FullName can not be null for this case) + objectExtensionsDto.Enums[enumProperty.Type.FullName] = CreateExtensionEnumDto(enumProperty); + } + } + + protected virtual ExtensionEnumDto CreateExtensionEnumDto(ExtensionPropertyConfiguration enumProperty) + { + var extensionEnumDto = new ExtensionEnumDto + { + Fields = new List(), + LocalizationResource = enumProperty.GetLocalizationResourceNameOrNull() + }; + + foreach (var enumValue in enumProperty.Type.GetEnumValues()) + { + extensionEnumDto.Fields.Add( + new ExtensionEnumFieldDto + { + Name = enumProperty.Type.GetEnumName(enumValue), + Value = enumValue + } + ); + } + + return extensionEnumDto; + } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs new file mode 100644 index 0000000000..1bcd513168 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.Serialization; + +namespace Volo.Abp +{ + public class AbpInitializationException : AbpException + { + /// + /// Creates a new object. + /// + public AbpInitializationException() + { + + } + + /// + /// Creates a new object. + /// + /// Exception message + public AbpInitializationException(string message) + : base(message) + { + + } + + /// + /// Creates a new object. + /// + /// Exception message + /// Inner exception + public AbpInitializationException(string message, Exception innerException) + : base(message, innerException) + { + + } + + /// + /// Constructor for serializing. + /// + public AbpInitializationException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleLoader.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleLoader.cs index 30bf523c1d..374e1adb78 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleLoader.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleLoader.cs @@ -105,7 +105,14 @@ namespace Volo.Abp.Modularity //PreConfigureServices foreach (var module in modules.Where(m => m.Instance is IPreConfigureServices)) { - ((IPreConfigureServices)module.Instance).PreConfigureServices(context); + try + { + ((IPreConfigureServices)module.Instance).PreConfigureServices(context); + } + catch (Exception ex) + { + throw new AbpInitializationException($"An error occurred during {nameof(IPreConfigureServices.PreConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + } } //ConfigureServices @@ -119,13 +126,27 @@ namespace Volo.Abp.Modularity } } - module.Instance.ConfigureServices(context); + try + { + module.Instance.ConfigureServices(context); + } + catch (Exception ex) + { + throw new AbpInitializationException($"An error occurred during {nameof(IAbpModule.ConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + } } //PostConfigureServices foreach (var module in modules.Where(m => m.Instance is IPostConfigureServices)) { - ((IPostConfigureServices)module.Instance).PostConfigureServices(context); + try + { + ((IPostConfigureServices)module.Instance).PostConfigureServices(context); + } + catch (Exception ex) + { + throw new AbpInitializationException($"An error occurred during {nameof(IPostConfigureServices.PostConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + } } foreach (var module in modules) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs index 8f25389b63..e594a24603 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs @@ -34,11 +34,18 @@ namespace Volo.Abp.Modularity { LogListOfModules(); - foreach (var Contributor in _lifecycleContributors) + foreach (var contributor in _lifecycleContributors) { foreach (var module in _moduleContainer.Modules) { - Contributor.Initialize(context, module.Instance); + try + { + contributor.Initialize(context, module.Instance); + } + catch (Exception ex) + { + throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + } } } @@ -59,11 +66,18 @@ namespace Volo.Abp.Modularity { var modules = _moduleContainer.Modules.Reverse().ToList(); - foreach (var Contributor in _lifecycleContributors) + foreach (var contributor in _lifecycleContributors) { foreach (var module in modules) { - Contributor.Shutdown(context, module.Instance); + try + { + contributor.Shutdown(context, module.Instance); + } + catch (Exception ex) + { + throw new AbpInitializationException($"An error occurred during the shutdown {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + } } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeHelper.cs index b388ef791d..192043a800 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeHelper.cs @@ -169,7 +169,7 @@ namespace Volo.Abp.Reflection { return Activator.CreateInstance(type); } - + return null; } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs index c1c8491dd6..2fa00e3caf 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs @@ -58,12 +58,14 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters return dictionary; } - private static object GetNormalizedValue(Dictionary dictionary, ObjectExtensionPropertyInfo property) + private static object GetNormalizedValue( + Dictionary dictionary, + ObjectExtensionPropertyInfo property) { var value = dictionary.GetOrDefault(property.Name); if (value == null) { - return null; + return property.GetDefaultValue(); } try diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableString.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizableString.cs similarity index 100% rename from framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableString.cs rename to framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizableString.cs diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs similarity index 100% rename from framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs rename to framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/StringLocalizerHelper.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/StringLocalizerHelper.cs new file mode 100644 index 0000000000..b6daf4a44d --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/StringLocalizerHelper.cs @@ -0,0 +1,50 @@ +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.Localization +{ + /// + /// This class is designed to be used internal by the framework. + /// + public static class AbpInternalLocalizationHelper + { + /// + /// Searches an array of keys in an array of localizers. + /// + /// + /// An array of localizers. Search the keys on the localizers. + /// Can contain null items in the array. + /// + /// + /// An array of keys. Search the keys on the localizers. + /// Should not contain null items in the array. + /// + /// + /// Return value if none of the localizers has none of the keys. + /// + /// + public static string LocalizeWithFallback( + IStringLocalizer[] localizers, + string[] keys, + string defaultValue) + { + foreach (var key in keys) + { + foreach (var localizer in localizers) + { + if (localizer == null) + { + continue; + } + + var localizedString = localizer[key]; + if (!localizedString.ResourceNotFound) + { + return localizedString.Value; + } + } + } + + return defaultValue; + } + } +} diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfigurationExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfigurationExtensions.cs new file mode 100644 index 0000000000..946fc04274 --- /dev/null +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfigurationExtensions.cs @@ -0,0 +1,32 @@ +using System; +using Volo.Abp.Localization; + +namespace Volo.Abp.ObjectExtending.Modularity +{ + public static class ExtensionPropertyConfigurationExtensions + { + public static string GetLocalizationResourceNameOrNull( + this ExtensionPropertyConfiguration property) + { + var resourceType = property.GetLocalizationResourceTypeOrNull(); + if (resourceType == null) + { + return null; + } + + return LocalizationResourceNameAttribute.GetName(resourceType); + } + + public static Type GetLocalizationResourceTypeOrNull( + this ExtensionPropertyConfiguration property) + { + if (property.DisplayName != null && + property.DisplayName is LocalizableString localizableString) + { + return localizableString.ResourceType; + } + + return null; + } + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/TypeHelper_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/TypeHelper_Tests.cs index 978bf9de54..b12a52e935 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/TypeHelper_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/TypeHelper_Tests.cs @@ -80,6 +80,7 @@ namespace Volo.Abp.Reflection TypeHelper.GetDefaultValue(typeof(byte)).ShouldBe(0); TypeHelper.GetDefaultValue(typeof(int)).ShouldBe(0); TypeHelper.GetDefaultValue(typeof(string)).ShouldBeNull(); + TypeHelper.GetDefaultValue(typeof(MyEnum)).ShouldBe(MyEnum.EnumValue0); } [Fact] @@ -94,5 +95,11 @@ namespace Volo.Abp.Reflection { } + + public enum MyEnum + { + EnumValue0, + EnumValue1, + } } } diff --git a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/ObjectExtensionManager_Tests.cs b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/ObjectExtensionManager_Tests.cs index 6386dc41ff..a751fdf20f 100644 --- a/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/ObjectExtensionManager_Tests.cs +++ b/framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/ObjectExtensionManager_Tests.cs @@ -138,23 +138,27 @@ namespace Volo.Abp.ObjectExtending .AddOrUpdateProperty("StringPropWithCustomDefaultValue", property => { property.DefaultValue = "custom-value"; + }) + .AddOrUpdateProperty("EnumProp", property => + { + property.DefaultValue = MyTestEnum.EnumValue2; }); _objectExtensionManager .GetPropertyOrNull("IntProp") - .DefaultValue.ShouldBe(0); + .GetDefaultValue().ShouldBe(0); _objectExtensionManager .GetPropertyOrNull("IntPropWithCustomDefaultValue") - .DefaultValue.ShouldBe(42); + .GetDefaultValue().ShouldBe(42); _objectExtensionManager .GetPropertyOrNull("BoolProp") - .DefaultValue.ShouldBe(false); + .GetDefaultValue().ShouldBe(false); _objectExtensionManager .GetPropertyOrNull("NullableIntProp") - .DefaultValue.ShouldBeNull(); + .GetDefaultValue().ShouldBeNull(); var propWithDefaultValueFactory = _objectExtensionManager .GetPropertyOrNull("NullableIntPropWithCustomDefaultValueFactory"); @@ -162,11 +166,15 @@ namespace Volo.Abp.ObjectExtending _objectExtensionManager .GetPropertyOrNull("StringProp") - .DefaultValue.ShouldBeNull(); + .GetDefaultValue().ShouldBeNull(); _objectExtensionManager .GetPropertyOrNull("StringPropWithCustomDefaultValue") - .DefaultValue.ShouldBe("custom-value"); + .GetDefaultValue().ShouldBe("custom-value"); + + _objectExtensionManager + .GetPropertyOrNull("EnumProp") + .GetDefaultValue().ShouldBe(MyTestEnum.EnumValue2); } private class MyExtensibleObject : ExtensibleObject