diff --git a/FluentValidation.AutoValidation.Shared/src/Extensions/TypeExtensions.cs b/FluentValidation.AutoValidation.Shared/src/Extensions/TypeExtensions.cs index 3d406e2..019bd3c 100644 --- a/FluentValidation.AutoValidation.Shared/src/Extensions/TypeExtensions.cs +++ b/FluentValidation.AutoValidation.Shared/src/Extensions/TypeExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; @@ -32,6 +33,13 @@ public static bool IsCustomType(this Type? type) return false; } + if (typeof(IEnumerable).IsAssignableFrom(type)) + { + var underlyingType = type.IsArray ? type.GetElementType() : type.GetGenericArguments().LastOrDefault(); + + return underlyingType != null && underlyingType.IsCustomType(); + } + return type.IsClass || type.IsValueType; } diff --git a/Tests/src/FluentValidation.AutoValidation.Shared/Extensions/TypeExtensionsTest.cs b/Tests/src/FluentValidation.AutoValidation.Shared/Extensions/TypeExtensionsTest.cs index 3920f6c..d99daa0 100644 --- a/Tests/src/FluentValidation.AutoValidation.Shared/Extensions/TypeExtensionsTest.cs +++ b/Tests/src/FluentValidation.AutoValidation.Shared/Extensions/TypeExtensionsTest.cs @@ -1,6 +1,7 @@ // ReSharper disable InconsistentNaming using System; +using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; using SharpGrip.FluentValidation.AutoValidation.Mvc.Attributes; using SharpGrip.FluentValidation.AutoValidation.Shared.Extensions; @@ -42,6 +43,87 @@ public void Test_IsCustomType() Assert.False(typeof(Uri).IsCustomType()); } + [Fact] + public void Test_IsCustomType_Collections() + { + Assert.True(typeof(ICollection).IsCustomType()); + Assert.True(typeof(ICollection).IsCustomType()); + Assert.True(typeof(ICollection).IsCustomType()); + Assert.False(typeof(ICollection).IsCustomType()); + Assert.False(typeof(ICollection).IsCustomType()); + Assert.False(typeof(ICollection).IsCustomType()); + + Assert.True(typeof(IList).IsCustomType()); + Assert.True(typeof(IList).IsCustomType()); + Assert.True(typeof(IList).IsCustomType()); + Assert.False(typeof(IList).IsCustomType()); + Assert.False(typeof(IList).IsCustomType()); + Assert.False(typeof(IList).IsCustomType()); + + Assert.True(typeof(List).IsCustomType()); + Assert.True(typeof(List).IsCustomType()); + Assert.True(typeof(List).IsCustomType()); + Assert.False(typeof(List).IsCustomType()); + Assert.False(typeof(List).IsCustomType()); + Assert.False(typeof(List).IsCustomType()); + + Assert.True(typeof(TestModelClass[]).IsCustomType()); + Assert.True(typeof(TestModelRecord[]).IsCustomType()); + Assert.True(typeof(TestModelStruct[]).IsCustomType()); + Assert.False(typeof(TestModelEnum[]).IsCustomType()); + Assert.False(typeof(Enum[]).IsCustomType()); + Assert.False(typeof(string[]).IsCustomType()); + + Assert.True(typeof(Dictionary).IsCustomType()); + Assert.True(typeof(Dictionary).IsCustomType()); + Assert.True(typeof(Dictionary).IsCustomType()); + Assert.False(typeof(Dictionary).IsCustomType()); + Assert.False(typeof(Dictionary).IsCustomType()); + Assert.False(typeof(Dictionary).IsCustomType()); + + Assert.True(typeof(HashSet).IsCustomType()); + Assert.True(typeof(HashSet).IsCustomType()); + Assert.True(typeof(HashSet).IsCustomType()); + Assert.False(typeof(HashSet).IsCustomType()); + Assert.False(typeof(HashSet).IsCustomType()); + Assert.False(typeof(HashSet).IsCustomType()); + + Assert.True(typeof(IEnumerable).IsCustomType()); + Assert.True(typeof(IEnumerable).IsCustomType()); + Assert.True(typeof(IEnumerable).IsCustomType()); + Assert.False(typeof(IEnumerable).IsCustomType()); + Assert.False(typeof(IEnumerable).IsCustomType()); + Assert.False(typeof(IEnumerable).IsCustomType()); + + Assert.True(typeof(IReadOnlyList).IsCustomType()); + Assert.True(typeof(IReadOnlyList).IsCustomType()); + Assert.True(typeof(IReadOnlyList).IsCustomType()); + Assert.False(typeof(IReadOnlyList).IsCustomType()); + Assert.False(typeof(IReadOnlyList).IsCustomType()); + Assert.False(typeof(IReadOnlyList).IsCustomType()); + + Assert.True(typeof(IReadOnlyCollection).IsCustomType()); + Assert.True(typeof(IReadOnlyCollection).IsCustomType()); + Assert.True(typeof(IReadOnlyCollection).IsCustomType()); + Assert.False(typeof(IReadOnlyCollection).IsCustomType()); + Assert.False(typeof(IReadOnlyCollection).IsCustomType()); + Assert.False(typeof(IReadOnlyCollection).IsCustomType()); + + Assert.True(typeof(ISet).IsCustomType()); + Assert.True(typeof(ISet).IsCustomType()); + Assert.True(typeof(ISet).IsCustomType()); + Assert.False(typeof(ISet).IsCustomType()); + Assert.False(typeof(ISet).IsCustomType()); + Assert.False(typeof(ISet).IsCustomType()); + + Assert.False(typeof(IAsyncEnumerable).IsCustomType()); + Assert.False(typeof(IAsyncEnumerable).IsCustomType()); + Assert.False(typeof(IAsyncEnumerable).IsCustomType()); + Assert.False(typeof(IAsyncEnumerable).IsCustomType()); + Assert.False(typeof(IAsyncEnumerable).IsCustomType()); + Assert.False(typeof(IAsyncEnumerable).IsCustomType()); + } + [Fact] public void Test_HasCustomAttribute() {