diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs index 2b38059ef8..5233f2accc 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; @@ -95,32 +97,40 @@ namespace Volo.Abp.Domain.Entities var lambdaBody = Expression.Equal(leftExpression, rightExpression); return Expression.Lambda>(lambdaBody, lambdaParam); } - + + private static readonly ConcurrentDictionary CachedPropertyInfo = + new ConcurrentDictionary(); + public static void TrySetId( IEntity entity, Func idFactory, bool checkForDisableGuidGenerationAttribute = false) { - //TODO: Can be optimized (by caching per entity type)? - var entityType = entity.GetType(); - var idProperty = entityType.GetProperty( - nameof(entity.Id) - ); + var property = CachedPropertyInfo.GetOrAdd( + entity.GetType().FullName + checkForDisableGuidGenerationAttribute, () => + { + var entityType = entity.GetType(); + var idProperty = entityType.GetProperties() + .Where(x => x.GetSetMethod(true) != null) + .FirstOrDefault(x => x.Name == nameof(entity.Id)); - if (idProperty == null || idProperty.GetSetMethod(true) == null) - { - return; - } + if (idProperty == null) + { + return null; + } - if (checkForDisableGuidGenerationAttribute) - { - if (idProperty.IsDefined(typeof(DisableIdGenerationAttribute), true)) - { - return; - } - } + if (checkForDisableGuidGenerationAttribute) + { + if (idProperty.IsDefined(typeof(DisableIdGenerationAttribute), true)) + { + return null; + } + } + + return idProperty; + }); - idProperty.SetValue(entity, idFactory()); + property?.SetValue(entity, idFactory()); } } } diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs index 2ad6a45b05..8d405f6907 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using Shouldly; using Xunit; @@ -33,6 +34,15 @@ namespace Volo.Abp.Domain.Entities myEntityDisablesIdGeneration.Id.ShouldBe(default); } + [Fact] + public static void SetId_NewIdFromBaseClass() + { + var idValue = Guid.NewGuid(); + var myNewIdEntity = new NewIdEntity(); + EntityHelper.TrySetId(myNewIdEntity, () => idValue, true); + myNewIdEntity.Id.ShouldBe(idValue); + } + private class MyEntityDerivedFromAggregateRoot : AggregateRoot { @@ -53,5 +63,14 @@ namespace Volo.Abp.Domain.Entities [DisableIdGeneration] public override Guid Id { get; protected set; } } + + public class NewIdEntity : Entity + { + public new Guid Id + { + get => base.Id; + set => base.Id = value; + } + } } }