From 159f1c8235ed1b98a963887069710a0a21cf3d1d Mon Sep 17 00:00:00 2001 From: David Hall Date: Fri, 6 Dec 2019 17:09:08 -0700 Subject: [PATCH] Added EnumInheritance and InheritsFrom extension methods. --- Core/Extensions/ReflectionExtensions.cs | 37 ++++++++++++++++++-- .../Core/Extensions/ReflectionExtensionsTests.cs | 39 ++++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Core/Extensions/ReflectionExtensions.cs b/Core/Extensions/ReflectionExtensions.cs index 57cc1944..40d38303 100644 --- a/Core/Extensions/ReflectionExtensions.cs +++ b/Core/Extensions/ReflectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -11,6 +12,17 @@ namespace Vanara.Extensions.Reflection { private const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase; + /// Get a sequence of types that represent all base types and interfaces. + /// The type to evaluate. + /// A sequence of types that represent all base types and interfaces. + public static IEnumerable EnumInheritance(this Type type) + { + while (type.BaseType != null) + yield return type = type.BaseType; + foreach (var i in type.GetInterfaces()) + yield return i; + } + /// Gets a named field value from an object. /// The expected type of the field to be returned. /// The object from which to retrieve the field. @@ -58,6 +70,28 @@ namespace Vanara.Extensions.Reflection catch { return defaultValue; } } + /// Determines if a type inherits from another type. The may be a generic type definition. + /// The type. + /// The base type. + /// + /// if is found in the inheritance list for ; + /// otherwise. + /// + public static bool InheritsFrom(this Type type, Type baseType) + { + return !(type is null) && !(baseType is null) || type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition().Equals(baseType) || + type.BaseType.InheritsFrom(baseType) || baseType.IsAssignableFrom(type) || type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition().Equals(baseType)); + } + + /// Determines if a type inherits from another type. The may be a generic type definition. + /// The base type. + /// The type. + /// + /// if is found in the inheritance list for ; + /// otherwise. + /// + public static bool InheritsFrom(this Type type) => type.InheritsFrom(typeof(T)); + /// /// Invokes a generic named method on an object with parameters and no return value. /// @@ -177,7 +211,6 @@ namespace Vanara.Extensions /// Extensions related to System.Reflection public static class ReflectionExtensions { - private const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase; private const BindingFlags staticBindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase; /// For a structure, gets either the result of the static Create method or the default. @@ -303,7 +336,7 @@ namespace Vanara.Extensions return (T)mi.Invoke(null, args); } -#if !(NETSTANDARD2_0) +#if !NETSTANDARD2_0 /// Invokes a method from a derived base class. /// The instance from the derived class for the method to invoke. /// The target object. diff --git a/UnitTests/Core/Extensions/ReflectionExtensionsTests.cs b/UnitTests/Core/Extensions/ReflectionExtensionsTests.cs index 0b79697a..d4f60b1a 100644 --- a/UnitTests/Core/Extensions/ReflectionExtensionsTests.cs +++ b/UnitTests/Core/Extensions/ReflectionExtensionsTests.cs @@ -6,6 +6,7 @@ using System.Drawing; using static Vanara.Extensions.ReflectionExtensions; using System.Collections; using System.Collections.Generic; +using System.Linq; namespace Vanara.Extensions.Tests { @@ -17,6 +18,18 @@ namespace Vanara.Extensions.Tests public string Str { get; set; } } + [Test] + public void EnumInheritanceTest() + { + var a = typeof(FooInt).EnumInheritance().ToArray(); + Assert.That(a, Has.Member(typeof(IFoo)).And.Member(typeof(IFoo))); + TestContext.WriteLine(string.Join(",", a.Cast())); + + a = typeof(Foo2).EnumInheritance().ToArray(); + Assert.That(a, Has.Member(typeof(Foo)).And.Member(typeof(IFoo))); + TestContext.WriteLine(string.Join(",", a.Cast())); + } + [Test()] public void GetPropertyValueTest() { @@ -98,6 +111,32 @@ namespace Vanara.Extensions.Tests } + private interface IFoo { } + private interface IFoo : IFoo { } + private interface IFoo : IFoo { } + private class Foo : IFoo { } + private class Foo : IFoo { } + private class Foo : IFoo { } + private class FooInt : IFoo { } + private class FooStringInt : IFoo { } + private class Foo2 : Foo { } + + [Test] + public void InhertisFromTest() + { + Assert.That(typeof(Foo).InheritsFrom()); + Assert.That(typeof(FooInt).InheritsFrom()); + Assert.That(typeof(FooInt).InheritsFrom(typeof(IFoo<>))); + Assert.That(typeof(FooInt).InheritsFrom>()); + Assert.That(typeof(FooInt).InheritsFrom>()); + Assert.That(typeof(FooInt).InheritsFrom(typeof(IFoo<,>))); + Assert.That(typeof(FooStringInt).InheritsFrom(typeof(IFoo<,>))); + Assert.That(typeof(FooStringInt).InheritsFrom>()); + Assert.That(typeof(Foo).InheritsFrom>()); + Assert.That(typeof(Foo2).InheritsFrom()); + Assert.That(typeof(Foo2).InheritsFrom()); + } + [Test()] public void InvokeMethodRetTest() {