diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMappingHelper.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMappingHelper.cs index 5949edaba9..3bc1a1389b 100644 --- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMappingHelper.cs +++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMappingHelper.cs @@ -55,10 +55,17 @@ public static class ObjectMappingHelper return true; } - if (type.IsGenericType && - supportedCollectionTypes.Contains(type.GetGenericTypeDefinition()) || + if ((type.IsGenericType && + supportedCollectionTypes.Contains(type.GetGenericTypeDefinition())) || type.GetInterfaces().Any(i => i.IsGenericType && supportedCollectionTypes.Contains(i.GetGenericTypeDefinition()))) { + if (!type.IsGenericType) + { + elementType = null!; + definitionGenericType = null!; + return false; + } + elementType = type.GetGenericArguments()[0]; definitionGenericType = type.GetGenericTypeDefinition(); if (definitionGenericType == typeof(IEnumerable<>) || diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ObjectMappingHelper_Tests.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ObjectMappingHelper_Tests.cs new file mode 100644 index 0000000000..c262dad81a --- /dev/null +++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ObjectMappingHelper_Tests.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Shouldly; +using Xunit; + +namespace Volo.Abp.ObjectMapping; + +public class ObjectMappingHelper_Tests +{ + [Fact] + public void IsCollectionGenericType_Should_Return_True_For_Standard_GenericCollection() + { + var result = ObjectMappingHelper.IsCollectionGenericType, List>( + out var sourceArg, out var destArg, out var defGenericType); + + result.ShouldBeTrue(); + sourceArg.ShouldBe(typeof(MappingTestSource)); + destArg.ShouldBe(typeof(MappingTestDestination)); + defGenericType.ShouldBe(typeof(List<>)); + } + + [Fact] + public void IsCollectionGenericType_Should_Return_True_For_Array() + { + var result = ObjectMappingHelper.IsCollectionGenericType( + out var sourceArg, out var destArg, out _); + + result.ShouldBeTrue(); + sourceArg.ShouldBe(typeof(MappingTestSource)); + destArg.ShouldBe(typeof(MappingTestDestination)); + } + + [Fact] + public void IsCollectionGenericType_Should_Normalize_IEnumerable_To_List() + { + var result = ObjectMappingHelper.IsCollectionGenericType, IEnumerable>( + out _, out _, out var defGenericType); + + result.ShouldBeTrue(); + defGenericType.ShouldBe(typeof(List<>)); + } + + [Fact] + public void IsCollectionGenericType_Should_Normalize_ICollection_To_Collection() + { + var result = ObjectMappingHelper.IsCollectionGenericType, ICollection>( + out _, out _, out var defGenericType); + + result.ShouldBeTrue(); + defGenericType.ShouldBe(typeof(Collection<>)); + } + + [Fact] + public void IsCollectionGenericType_Should_Return_False_For_NonCollection() + { + var result = ObjectMappingHelper.IsCollectionGenericType( + out _, out _, out _); + + result.ShouldBeFalse(); + } + + [Fact] + public void IsCollectionGenericType_Should_Return_False_For_NonGeneric_DerivedCollection() + { + var result = ObjectMappingHelper.IsCollectionGenericType, MappingTestDestinationList>( + out _, out _, out _); + + result.ShouldBeFalse(); + } +} + +public class MappingTestSource +{ + public string Value { get; set; } = ""; +} + +public class MappingTestDestination +{ + public string Value { get; set; } = ""; +} + +public class MappingTestDestinationList : List +{ +}