From 50e9eff54d906fe957d5f4f1fbe1efc9f558321f Mon Sep 17 00:00:00 2001 From: vcup Date: Sat, 11 May 2024 10:41:16 +0800 Subject: [PATCH 1/9] feat: better enumerable graph type determing --- .../Extensions/ReflectionExtensions.cs | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index 8be70f5..6ff0360 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -30,6 +30,29 @@ public static bool IsNullableType(this TypeInfo type) return type.IsGenericType(typeof(Nullable<>)); } + public static bool ImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = false) + { + if (!interfaceType.IsInterface) return false; + while (type is not null) + { + var interfaces = type.GetInterfaces() as IEnumerable; + if (fuseGeneric) + { + interfaces = interfaces + .Where(t => t.IsGenericType) + .Select(t => t.GetGenericTypeDefinition()) + .Concat(interfaces.Where(t => !t.IsGenericType)); + } + + if (interfaces.Any(t => t == interfaceType || t.ImplementInterface(interfaceType, fuseGeneric))) + return true; + type = type.BaseType; + } + + return false; + } + + public static TypeInfo BaseType(this TypeInfo type) { return type.IsNullableType() @@ -63,8 +86,8 @@ public static bool IsPrimitiveGraphType(this TypeInfo type) public static bool IsEnumerableGraphType(this TypeInfo type) { - return type.IsGenericType(typeof(List<>)) || - type.IsGenericType(typeof(IList<>)) || + return type.ImplementInterface(typeof(ICollection<>), true) || + type.ImplementInterface(typeof(IReadOnlyCollection<>), true) || type.IsGenericType(typeof(IEnumerable<>)) || (type.IsGenericType && type.DeclaringType == typeof(Enumerable)) || // Handles internal Iterator implementations for LINQ; for reference https://referencesource.microsoft.com/#system.core/System/Linq/Enumerable.cs type.IsArray; From 256caadc1ba134510912c864356f25a84578ca5a Mon Sep 17 00:00:00 2001 From: miryo Date: Sat, 11 May 2024 13:36:51 +0800 Subject: [PATCH 2/9] fix: failed unit tests --- .../Extensions/ReflectionExtensions.cs | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index 6ff0360..002b80e 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -30,28 +30,33 @@ public static bool IsNullableType(this TypeInfo type) return type.IsGenericType(typeof(Nullable<>)); } - public static bool ImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = false) + public static Type GetImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = true) { - if (!interfaceType.IsInterface) return false; + if (!interfaceType.IsInterface) return null; while (type is not null) { - var interfaces = type.GetInterfaces() as IEnumerable; - if (fuseGeneric) + var interfaces = type.GetInterfaces(); + var mayFusedGenericInterface = fuseGeneric + ? interfaces.Select(t => t.IsGenericType ? t.GetGenericTypeDefinition() : t).ToArray() + : interfaces; + + for (int i = 0; i < interfaces.Length; i++) { - interfaces = interfaces - .Where(t => t.IsGenericType) - .Select(t => t.GetGenericTypeDefinition()) - .Concat(interfaces.Where(t => !t.IsGenericType)); + var @interface = mayFusedGenericInterface[i]; + if (@interface == interfaceType) return interfaces[i]; + var ni = @interface.GetImplementInterface(interfaceType, fuseGeneric); + if (ni is not null) return ni; } - if (interfaces.Any(t => t == interfaceType || t.ImplementInterface(interfaceType, fuseGeneric))) - return true; type = type.BaseType; } - return false; + return null; } + public static bool ImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = true) => + type.GetImplementInterface(interfaceType, fuseGeneric) is not null; + public static TypeInfo BaseType(this TypeInfo type) { @@ -68,7 +73,7 @@ public static TypeInfo TypeParameter(this TypeInfo type) } return type.IsGenericType ? type.GenericTypeArguments.First().GetTypeInfo() - : null; + : type.TypeParameterCollection(); } public static TypeInfo TypeParameter(this GraphTypeInfo type) @@ -76,6 +81,11 @@ public static TypeInfo TypeParameter(this GraphTypeInfo type) return type.TypeRepresentation.TypeParameter(); } + public static TypeInfo TypeParameterCollection(this TypeInfo type) => ( + type.GetImplementInterface(typeof(ICollection<>)) ?? + type.GetImplementInterface(typeof(IReadOnlyList<>)) + )?.GetTypeInfo(); + public static bool IsPrimitiveGraphType(this TypeInfo type) { return type.IsPrimitive || @@ -86,7 +96,7 @@ public static bool IsPrimitiveGraphType(this TypeInfo type) public static bool IsEnumerableGraphType(this TypeInfo type) { - return type.ImplementInterface(typeof(ICollection<>), true) || + return type.ImplementInterface(typeof(ICollection<>)) || type.ImplementInterface(typeof(IReadOnlyCollection<>), true) || type.IsGenericType(typeof(IEnumerable<>)) || (type.IsGenericType && type.DeclaringType == typeof(Enumerable)) || // Handles internal Iterator implementations for LINQ; for reference https://referencesource.microsoft.com/#system.core/System/Linq/Enumerable.cs @@ -116,16 +126,19 @@ public static TypeInfo GetTypeRepresentation(this TypeInfo typeInfo) { typeInfo = typeInfo.TypeParameter(); } + if (typeInfo.IsGenericType(typeof(IObservable<>))) { typeInfo = typeInfo.TypeParameter(); } + if (typeInfo.IsGenericType(typeof(Nullable<>)) || typeInfo.IsGenericType(typeof(NonNull<>)) || typeInfo.IsGenericType(typeof(Optional<>))) { typeInfo = typeInfo.TypeParameter(); } + return typeInfo; } From 3a7c51b5cdae16953a44655420aea37347bf7799 Mon Sep 17 00:00:00 2001 From: miryo Date: Sat, 11 May 2024 17:30:22 +0800 Subject: [PATCH 3/9] feat: unit tests for GetImplementInterface --- .../Extensions/ReflectionExtensions.cs | 5 ++ .../Extensions/ReflectionExtensionsTests.cs | 74 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index 002b80e..5bf59f7 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -33,6 +33,11 @@ public static bool IsNullableType(this TypeInfo type) public static Type GetImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = true) { if (!interfaceType.IsInterface) return null; + fuseGeneric &= interfaceType.IsGenericType; + if (type.IsGenericType && fuseGeneric + ? type.GetGenericTypeDefinition() == interfaceType.GetGenericTypeDefinition() + : type == interfaceType + ) return interfaceType; while (type is not null) { var interfaces = type.GetInterfaces(); diff --git a/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs b/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs new file mode 100644 index 0000000..3182f35 --- /dev/null +++ b/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs @@ -0,0 +1,74 @@ +using System; +using GraphQL.Conventions.Types.Resolution.Extensions; +using Xunit; + +namespace Tests.Types.Resolution.Extensions +{ + public class ReflectionExtensionsTests + { + [Theory] + [MemberData(nameof(GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly__Data))] + public void GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly(Type type, Type assignableInterface) + => Assert.IsTrue(type.ImplementInterface(assignableInterface, false)); + + public static TheoryData GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly__Data() => + new() + { + { typeof(ITestInterface1), typeof(ITestInterface1) }, + { typeof(ITestInterface2), typeof(ITestInterface1) }, + { typeof(ITestInterface2), typeof(ITestInterface2) }, + { typeof(TestClass11), typeof(ITestInterface1) }, + { typeof(TestClass12), typeof(ITestInterface1) }, + { typeof(TestClass12), typeof(ITestInterface2) }, + { typeof(TestClass2), typeof(ITestInterface1) }, + { typeof(TestClass2), typeof(ITestInterface1) }, + { typeof(TestClass2), typeof(ITestInterface2) }, + }; + + [Theory] + [MemberData(nameof(GetImplementInterface_WithFuse_AcquireSpecifyInterfaceOnly__Data))] + public void GetImplementInterface_WithFuse_AcquireSpecifyInterfaceOnly(Type type, Type assignableInterface) => + Assert.IsTrue(type.ImplementInterface(assignableInterface)); + + public static TheoryData GetImplementInterface_WithFuse_AcquireSpecifyInterfaceOnly__Data() => + new() + { + { typeof(ITestInterface1), typeof(ITestInterface1<>) }, + { typeof(ITestInterface2), typeof(ITestInterface1<>) }, + { typeof(ITestInterface2), typeof(ITestInterface2<>) }, + { typeof(TestClass11), typeof(ITestInterface1<>) }, + // + { typeof(ITestInterface1), typeof(ITestInterface1<>) }, + { typeof(ITestInterface2), typeof(ITestInterface1<>) }, + { typeof(ITestInterface2), typeof(ITestInterface2<>) }, + { typeof(TestClass11), typeof(ITestInterface1<>) }, + // + { typeof(TestClass12), typeof(ITestInterface1<>) }, + { typeof(TestClass12), typeof(ITestInterface2<>) }, + { typeof(TestClass2), typeof(ITestInterface1<>) }, + { typeof(TestClass2), typeof(ITestInterface2<>) }, + }; + + private interface ITestInterface1 + { + // ReSharper disable once UnusedMember.Global + T Item => throw new NotImplementedException(); + } + + private interface ITestInterface2 : ITestInterface1 + { + } + + private class TestClass11 : ITestInterface1 + { + } + + private class TestClass12 : ITestInterface2 + { + } + + private class TestClass2 : ITestInterface2, ITestInterface1 + { + } + } +} From 813fa3a41a554f35bee7b9bd5112b6fb7ec1465e Mon Sep 17 00:00:00 2001 From: miryo Date: Sat, 11 May 2024 17:38:05 +0800 Subject: [PATCH 4/9] feat: unit tests for IsEnumerableGraphType --- .../Extensions/ReflectionExtensionsTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs b/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs index 3182f35..186201f 100644 --- a/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs +++ b/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Reflection; using GraphQL.Conventions.Types.Resolution.Extensions; using Xunit; @@ -6,6 +9,25 @@ namespace Tests.Types.Resolution.Extensions { public class ReflectionExtensionsTests { + [Theory] + [MemberData(nameof(IsEnumerableGraphType_Should_ReturnTrue_For_Common_Collection_Types__Data))] + public void IsEnumerableGraphType_Should_ReturnTrue_For_Common_Collection_Types(Type type) + { + Assert.IsTrue(type.GetTypeInfo().IsEnumerableGraphType()); + } + + public static TheoryData IsEnumerableGraphType_Should_ReturnTrue_For_Common_Collection_Types__Data() => new() + { + typeof(IEnumerable<>), + typeof(ConcurrentQueue<>), + typeof(HashSet<>), + typeof(int[]), + typeof(List<>), + typeof(IList<>), + typeof(IReadOnlyList<>), + typeof(IReadOnlyCollection<>) + }; + [Theory] [MemberData(nameof(GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly__Data))] public void GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly(Type type, Type assignableInterface) From 6b645f6c5fff8b32ac2e9e5d4ed34d715d2a34d0 Mon Sep 17 00:00:00 2001 From: vcup Date: Sun, 12 May 2024 11:57:26 +0800 Subject: [PATCH 5/9] chore: run 'dotnet format' --- .../Resolution/Extensions/ReflectionExtensions.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index 5bf59f7..c7a0e3d 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -32,12 +32,14 @@ public static bool IsNullableType(this TypeInfo type) public static Type GetImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = true) { - if (!interfaceType.IsInterface) return null; + if (!interfaceType.IsInterface) + return null; fuseGeneric &= interfaceType.IsGenericType; if (type.IsGenericType && fuseGeneric ? type.GetGenericTypeDefinition() == interfaceType.GetGenericTypeDefinition() : type == interfaceType - ) return interfaceType; + ) + return interfaceType; while (type is not null) { var interfaces = type.GetInterfaces(); @@ -48,9 +50,11 @@ public static Type GetImplementInterface(this Type type, Type interfaceType, boo for (int i = 0; i < interfaces.Length; i++) { var @interface = mayFusedGenericInterface[i]; - if (@interface == interfaceType) return interfaces[i]; + if (@interface == interfaceType) + return interfaces[i]; var ni = @interface.GetImplementInterface(interfaceType, fuseGeneric); - if (ni is not null) return ni; + if (ni is not null) + return ni; } type = type.BaseType; From ffd0b99a9467519c2cb1942fe5d869341795b4ac Mon Sep 17 00:00:00 2001 From: vcup Date: Wed, 15 May 2024 14:47:41 +0800 Subject: [PATCH 6/9] fix: GetImplementInterface may return type that contain generic parameter --- .../Types/Resolution/Extensions/ReflectionExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index c7a0e3d..d268b98 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -49,8 +49,8 @@ public static Type GetImplementInterface(this Type type, Type interfaceType, boo for (int i = 0; i < interfaces.Length; i++) { - var @interface = mayFusedGenericInterface[i]; - if (@interface == interfaceType) + var @interface = interfaces[i]; + if (mayFusedGenericInterface[i] == interfaceType) return interfaces[i]; var ni = @interface.GetImplementInterface(interfaceType, fuseGeneric); if (ni is not null) From d50216774730cc45547f1117b42874660e9fd216 Mon Sep 17 00:00:00 2001 From: vcup Date: Tue, 21 May 2024 10:19:05 +0800 Subject: [PATCH 7/9] feat: avoid IDictionary recognize as enumerable graph type --- .../Types/Resolution/Extensions/ReflectionExtensions.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index d268b98..1d8485b 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -105,6 +105,10 @@ public static bool IsPrimitiveGraphType(this TypeInfo type) public static bool IsEnumerableGraphType(this TypeInfo type) { + if (type.ImplementInterface(typeof(IDictionary)) || type.ImplementInterface(typeof(IDictionary<,>))) + { + return false; + } return type.ImplementInterface(typeof(ICollection<>)) || type.ImplementInterface(typeof(IReadOnlyCollection<>), true) || type.IsGenericType(typeof(IEnumerable<>)) || From 9218fbe4589510c73133d80fb3a7c140ff9962fd Mon Sep 17 00:00:00 2001 From: vcup Date: Tue, 21 May 2024 10:20:36 +0800 Subject: [PATCH 8/9] chore: remove unnecessary default parameter --- .../Types/Resolution/Extensions/ReflectionExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index 1d8485b..394282d 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -110,7 +110,7 @@ public static bool IsEnumerableGraphType(this TypeInfo type) return false; } return type.ImplementInterface(typeof(ICollection<>)) || - type.ImplementInterface(typeof(IReadOnlyCollection<>), true) || + type.ImplementInterface(typeof(IReadOnlyCollection<>)) || type.IsGenericType(typeof(IEnumerable<>)) || (type.IsGenericType && type.DeclaringType == typeof(Enumerable)) || // Handles internal Iterator implementations for LINQ; for reference https://referencesource.microsoft.com/#system.core/System/Linq/Enumerable.cs type.IsArray; From eba2066a67b441b5e9ed9db360735c3f71772b23 Mon Sep 17 00:00:00 2001 From: Tommy Lillehagen Date: Sat, 1 Jun 2024 07:36:47 +0100 Subject: [PATCH 9/9] chore: add dictionary test case and rename methods --- .../Extensions/ReflectionExtensions.cs | 26 +++++++------ .../Extensions/ReflectionExtensionsTests.cs | 38 +++++++++++++------ 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs index 394282d..0207af0 100644 --- a/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs +++ b/src/GraphQL.Conventions/Types/Resolution/Extensions/ReflectionExtensions.cs @@ -30,16 +30,19 @@ public static bool IsNullableType(this TypeInfo type) return type.IsGenericType(typeof(Nullable<>)); } - public static Type GetImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = true) + public static Type GetImplementationInterface(this Type type, Type interfaceType, bool fuseGeneric = true) { if (!interfaceType.IsInterface) return null; + fuseGeneric &= interfaceType.IsGenericType; if (type.IsGenericType && fuseGeneric ? type.GetGenericTypeDefinition() == interfaceType.GetGenericTypeDefinition() - : type == interfaceType - ) + : type == interfaceType) + { return interfaceType; + } + while (type is not null) { var interfaces = type.GetInterfaces(); @@ -52,7 +55,7 @@ public static Type GetImplementInterface(this Type type, Type interfaceType, boo var @interface = interfaces[i]; if (mayFusedGenericInterface[i] == interfaceType) return interfaces[i]; - var ni = @interface.GetImplementInterface(interfaceType, fuseGeneric); + var ni = @interface.GetImplementationInterface(interfaceType, fuseGeneric); if (ni is not null) return ni; } @@ -63,8 +66,8 @@ public static Type GetImplementInterface(this Type type, Type interfaceType, boo return null; } - public static bool ImplementInterface(this Type type, Type interfaceType, bool fuseGeneric = true) => - type.GetImplementInterface(interfaceType, fuseGeneric) is not null; + public static bool IsImplementingInterface(this Type type, Type interfaceType, bool fuseGeneric = true) => + type.GetImplementationInterface(interfaceType, fuseGeneric) is not null; public static TypeInfo BaseType(this TypeInfo type) @@ -91,8 +94,8 @@ public static TypeInfo TypeParameter(this GraphTypeInfo type) } public static TypeInfo TypeParameterCollection(this TypeInfo type) => ( - type.GetImplementInterface(typeof(ICollection<>)) ?? - type.GetImplementInterface(typeof(IReadOnlyList<>)) + type.GetImplementationInterface(typeof(ICollection<>)) ?? + type.GetImplementationInterface(typeof(IReadOnlyList<>)) )?.GetTypeInfo(); public static bool IsPrimitiveGraphType(this TypeInfo type) @@ -105,12 +108,13 @@ public static bool IsPrimitiveGraphType(this TypeInfo type) public static bool IsEnumerableGraphType(this TypeInfo type) { - if (type.ImplementInterface(typeof(IDictionary)) || type.ImplementInterface(typeof(IDictionary<,>))) + if (type.IsImplementingInterface(typeof(IDictionary)) || type.IsImplementingInterface(typeof(IDictionary<,>))) { return false; } - return type.ImplementInterface(typeof(ICollection<>)) || - type.ImplementInterface(typeof(IReadOnlyCollection<>)) || + + return type.IsImplementingInterface(typeof(ICollection<>)) || + type.IsImplementingInterface(typeof(IReadOnlyCollection<>)) || type.IsGenericType(typeof(IEnumerable<>)) || (type.IsGenericType && type.DeclaringType == typeof(Enumerable)) || // Handles internal Iterator implementations for LINQ; for reference https://referencesource.microsoft.com/#system.core/System/Linq/Enumerable.cs type.IsArray; diff --git a/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs b/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs index 186201f..dd9b32a 100644 --- a/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs +++ b/test/GraphQL.Conventions.Tests/Types/Resolution/Extensions/ReflectionExtensionsTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection; @@ -10,13 +11,13 @@ namespace Tests.Types.Resolution.Extensions public class ReflectionExtensionsTests { [Theory] - [MemberData(nameof(IsEnumerableGraphType_Should_ReturnTrue_For_Common_Collection_Types__Data))] - public void IsEnumerableGraphType_Should_ReturnTrue_For_Common_Collection_Types(Type type) + [MemberData(nameof(IsEnumerableGraphType_Should_Return_True_For_Common_Collection_Types_Data))] + public void IsEnumerableGraphType_Should_Return_True_For_Common_Collection_Types(Type type) { Assert.IsTrue(type.GetTypeInfo().IsEnumerableGraphType()); } - public static TheoryData IsEnumerableGraphType_Should_ReturnTrue_For_Common_Collection_Types__Data() => new() + public static TheoryData IsEnumerableGraphType_Should_Return_True_For_Common_Collection_Types_Data() => new() { typeof(IEnumerable<>), typeof(ConcurrentQueue<>), @@ -25,15 +26,28 @@ public void IsEnumerableGraphType_Should_ReturnTrue_For_Common_Collection_Types( typeof(List<>), typeof(IList<>), typeof(IReadOnlyList<>), - typeof(IReadOnlyCollection<>) + typeof(IReadOnlyCollection<>), }; [Theory] - [MemberData(nameof(GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly__Data))] - public void GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly(Type type, Type assignableInterface) - => Assert.IsTrue(type.ImplementInterface(assignableInterface, false)); + [MemberData(nameof(IsEnumerableGraphType_Should_Return_False_For_Common_Dictionary_Types_Data))] + public void IsEnumerableGraphType_Should_Return_False_For_Common_Dictionary_Types(Type type) + { + Assert.IsFalse(type.GetTypeInfo().IsEnumerableGraphType()); + } + + public static TheoryData IsEnumerableGraphType_Should_Return_False_For_Common_Dictionary_Types_Data() => new() + { + typeof(IDictionary<,>), + typeof(IDictionary), + }; + + [Theory] + [MemberData(nameof(GetImplementationInterface_WithoutFuse_AcquireSpecifiedInterfaceOnly_Data))] + public void GetImplementationInterface_WithoutFuse_AcquireSpecifiedInterfaceOnly(Type type, Type assignableInterface) + => Assert.IsTrue(type.IsImplementingInterface(assignableInterface, false)); - public static TheoryData GetImplementInterface_WithoutFuse_AcquireSpecifyInterfaceOnly__Data() => + public static TheoryData GetImplementationInterface_WithoutFuse_AcquireSpecifiedInterfaceOnly_Data() => new() { { typeof(ITestInterface1), typeof(ITestInterface1) }, @@ -48,11 +62,11 @@ public static TheoryData GetImplementInterface_WithoutFuse_AcquireSp }; [Theory] - [MemberData(nameof(GetImplementInterface_WithFuse_AcquireSpecifyInterfaceOnly__Data))] - public void GetImplementInterface_WithFuse_AcquireSpecifyInterfaceOnly(Type type, Type assignableInterface) => - Assert.IsTrue(type.ImplementInterface(assignableInterface)); + [MemberData(nameof(GetImplementationInterface_WithFuse_AcquireSpecifiedInterfaceOnly_Data))] + public void GetImplementationInterface_WithFuse_AcquireSpecifiedInterfaceOnly(Type type, Type assignableInterface) => + Assert.IsTrue(type.IsImplementingInterface(assignableInterface)); - public static TheoryData GetImplementInterface_WithFuse_AcquireSpecifyInterfaceOnly__Data() => + public static TheoryData GetImplementationInterface_WithFuse_AcquireSpecifiedInterfaceOnly_Data() => new() { { typeof(ITestInterface1), typeof(ITestInterface1<>) },