diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/HasExtraPropertiesExtensions.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/HasExtraPropertiesExtensions.cs new file mode 100644 index 0000000000..a16373eedc --- /dev/null +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/HasExtraPropertiesExtensions.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using Volo.Abp.Reflection; + +namespace Volo.Abp.Data +{ + public static class HasExtraPropertiesExtensions + { + public static bool HasProperty(this IHasExtraProperties source, string name) + { + return source.ExtraProperties.ContainsKey(name); + } + + public static object GetProperty(this IHasExtraProperties source, string name) + { + return source.ExtraProperties?.GetOrDefault(name); + } + + public static TProperty GetProperty(this IHasExtraProperties source, string name) + { + var value = source.GetProperty(name); + if (value == default) + { + return default; + } + + if (TypeHelper.IsPrimitiveExtended(typeof(TProperty), includeEnums: true)) + { + return (TProperty)Convert.ChangeType(value, typeof(TProperty), CultureInfo.InvariantCulture); + } + + throw new AbpException("GetProperty does not support non-primitive types. Use non-generic GetProperty method and handle type casting manually."); + } + + public static TSource SetProperty(this TSource source, string name, object value) + where TSource : IHasExtraProperties + { + source.ExtraProperties[name] = value; + return source; + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs index adcad00e17..67eff13572 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/ExtraProperties_Tests.cs @@ -1,6 +1,6 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Shouldly; +using Volo.Abp.Data; using Volo.Abp.Modularity; using Volo.Abp.TestApp.Domain; using Xunit; @@ -21,20 +21,20 @@ namespace Volo.Abp.TestApp.Testing public async Task Should_Get_An_Extra_Property() { var london = await CityRepository.FindByNameAsync("London"); - london.ExtraProperties.ContainsKey("Population").ShouldBeTrue(); - london.ExtraProperties["Population"].To().ShouldBe(10_470_000); + london.HasProperty("Population").ShouldBeTrue(); + london.GetProperty("Population").ShouldBe(10_470_000); } [Fact] public async Task Should_Add_An_Extra_Property() { var london = await CityRepository.FindByNameAsync("London"); - london.ExtraProperties["AreaAsKm"] = 1572; + london.SetProperty("AreaAsKm", 1572); await CityRepository.UpdateAsync(london); var london2 = await CityRepository.FindByNameAsync("London"); - london2.ExtraProperties.ContainsKey("AreaAsKm").ShouldBeTrue(); - london2.ExtraProperties["AreaAsKm"].To().ShouldBe(1572); + london2.HasProperty("AreaAsKm").ShouldBeTrue(); + london2.GetProperty("AreaAsKm").ShouldBe(1572); } [Fact] @@ -46,8 +46,8 @@ namespace Volo.Abp.TestApp.Testing await CityRepository.UpdateAsync(london); var london2 = await CityRepository.FindByNameAsync("London"); - london2.ExtraProperties.ContainsKey("Population").ShouldBeTrue(); - london2.ExtraProperties["Population"].To().ShouldBe(11_000_042); + london2.HasProperty("Population").ShouldBeTrue(); + london2.GetProperty("Population").ShouldBe(11_000_042); } } }