From ab188c6dc854612158c6398f76877c5ad47ffb03 Mon Sep 17 00:00:00 2001 From: namtab00 Date: Thu, 8 Feb 2024 01:02:03 +0100 Subject: [PATCH] add ObjectHelper support for property resolution for value types --- .../Volo.Abp.Core/Volo/Abp/ObjectHelper.cs | 47 ++++++++++++------- .../Volo/Abp/ObjectHelper_Tests.cs | 35 ++++++++++++++ 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs index 3ba332afab..c4bdc67a2a 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs @@ -9,8 +9,7 @@ namespace Volo.Abp; public static class ObjectHelper { - private static readonly ConcurrentDictionary CachedObjectProperties = - new ConcurrentDictionary(); + private static readonly ConcurrentDictionary _cachedObjectProperties = new(); public static void TrySetProperty( TObject obj, @@ -27,37 +26,53 @@ public static class ObjectHelper Func valueFactory, params Type[]? ignoreAttributeTypes) { - var cacheKey = $"{obj?.GetType().FullName}-" + - $"{propertySelector}-" + - $"{(ignoreAttributeTypes != null ? "-" + string.Join("-", ignoreAttributeTypes.Select(x => x.FullName)) : "")}"; + var cacheKey = + $"{obj?.GetType().FullName}-{propertySelector}-{(ignoreAttributeTypes != null ? "-" + string.Join("-", ignoreAttributeTypes.Select(x => x.FullName)) : "")}"; - var property = CachedObjectProperties.GetOrAdd(cacheKey, () => + var property = _cachedObjectProperties.GetOrAdd(cacheKey, PropertyFactory); + + property?.SetValue(obj, valueFactory(obj)); + return; + + PropertyInfo? PropertyFactory(string _) { - if (propertySelector.Body.NodeType != ExpressionType.MemberAccess) + MemberExpression? memberExpression; + switch (propertySelector.Body.NodeType) + { + case ExpressionType.Convert: { + memberExpression = propertySelector.Body.As().Operand as MemberExpression; + break; + } + case ExpressionType.MemberAccess: { + memberExpression = propertySelector.Body.As(); + break; + } + default: { + return null; + } + } + + if (memberExpression == null) { return null; } - var memberExpression = propertySelector.Body.As(); - var propertyInfo = obj?.GetType().GetProperties().FirstOrDefault(x => - x.Name == memberExpression.Member.Name && - x.GetSetMethod(true) != null); + var propertyInfo = obj?.GetType() + .GetProperties() + .FirstOrDefault(x => x.Name == memberExpression.Member.Name && x.GetSetMethod(true) != null); if (propertyInfo == null) { return null; } - if (ignoreAttributeTypes != null && - ignoreAttributeTypes.Any(ignoreAttribute => propertyInfo.IsDefined(ignoreAttribute, true))) + if (ignoreAttributeTypes != null && ignoreAttributeTypes.Any(ignoreAttribute => propertyInfo.IsDefined(ignoreAttribute, true))) { return null; } return propertyInfo; - }); - - property?.SetValue(obj, valueFactory(obj)); + } } } diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs index 59c811c88b..f23d54cf29 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs @@ -39,6 +39,30 @@ public class ObjectHelper_Tests testClass.ChildClass.Name.ShouldBe("NewChildName"); } + [Fact] + public void TrySetPropertyWithValueType_SetsCorrectly() + { + // Arrange + var testClass = new MyClass(); + const long newValue = 10; + + // Act & Assert + ObjectHelper.TrySetProperty(testClass, x => x.Number, () => newValue); + testClass.Number.ShouldBe(newValue); + + ObjectHelper.TrySetProperty(testClass, x => x.Number2, () => newValue); + testClass.Number2.ShouldBe(newValue); + + ObjectHelper.TrySetProperty(testClass, x => x.Number3, () => newValue); + testClass.Number3.ShouldBe(newValue); + + ObjectHelper.TrySetProperty(testClass, x => x.Number4, () => newValue); + testClass.Number4.ShouldBe(0); // readonly + + ObjectHelper.TrySetProperty(testClass, x => x.Number5, () => newValue, ignoreAttributeTypes: typeof(IgnoreDataMemberAttribute)); + testClass.Number5.ShouldNotBe(newValue); // ignore by attribute + } + class MyClass { public string Name { get; set; } @@ -52,6 +76,17 @@ public class ObjectHelper_Tests [IgnoreDataMember] public string Name5 { get; } + public long Number { get; set; } + + public long Number2 { get; protected set; } + + public long Number3 { get; private set; } + + public long Number4 { get; } + + [IgnoreDataMember] + public long Number5 { get; } + public MyChildClass ChildClass { get; set; } public MyClass()