Added EnumInheritance and InheritsFrom extension methods.

pull/83/head
David Hall 2019-12-06 17:09:08 -07:00
parent 2cb4245f37
commit 159f1c8235
2 changed files with 74 additions and 2 deletions

View File

@ -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;
/// <summary>Get a sequence of types that represent all base types and interfaces.</summary>
/// <param name="type">The type to evaluate.</param>
/// <returns>A sequence of types that represent all base types and interfaces.</returns>
public static IEnumerable<Type> EnumInheritance(this Type type)
{
while (type.BaseType != null)
yield return type = type.BaseType;
foreach (var i in type.GetInterfaces())
yield return i;
}
/// <summary>Gets a named field value from an object.</summary>
/// <typeparam name="T">The expected type of the field to be returned.</typeparam>
/// <param name="obj">The object from which to retrieve the field.</param>
@ -58,6 +70,28 @@ namespace Vanara.Extensions.Reflection
catch { return defaultValue; }
}
/// <summary>Determines if a type inherits from another type. The <paramref name="baseType"/> may be a generic type definition.</summary>
/// <param name="type">The type.</param>
/// <param name="baseType">The base type.</param>
/// <returns>
/// <see langword="true"/> if <paramref name="baseType"/> is found in the inheritance list for <paramref name="type"/>;
/// <see langword="false"/> otherwise.
/// </returns>
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));
}
/// <summary>Determines if a type inherits from another type. The <typeparamref name="T"/> may be a generic type definition.</summary>
/// <typeparam name="T">The base type.</typeparam>
/// <param name="type">The type.</param>
/// <returns>
/// <see langword="true"/> if <typeparamref name="T"/> is found in the inheritance list for <paramref name="type"/>;
/// <see langword="false"/> otherwise.
/// </returns>
public static bool InheritsFrom<T>(this Type type) => type.InheritsFrom(typeof(T));
/// <summary>
/// Invokes a generic named method on an object with parameters and no return value.
/// </summary>
@ -177,7 +211,6 @@ namespace Vanara.Extensions
/// <summary>Extensions related to <c>System.Reflection</c></summary>
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;
/// <summary>For a structure, gets either the result of the static Create method or the default.</summary>
@ -303,7 +336,7 @@ namespace Vanara.Extensions
return (T)mi.Invoke(null, args);
}
#if !(NETSTANDARD2_0)
#if !NETSTANDARD2_0
/// <summary>Invokes a method from a derived base class.</summary>
/// <param name="methodInfo">The <see cref="MethodInfo"/> instance from the derived class for the method to invoke.</param>
/// <param name="targetObject">The target object.</param>

View File

@ -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<int>)).And.Member(typeof(IFoo)));
TestContext.WriteLine(string.Join(",", a.Cast<Type>()));
a = typeof(Foo2).EnumInheritance().ToArray();
Assert.That(a, Has.Member(typeof(Foo)).And.Member(typeof(IFoo)));
TestContext.WriteLine(string.Join(",", a.Cast<Type>()));
}
[Test()]
public void GetPropertyValueTest()
{
@ -98,6 +111,32 @@ namespace Vanara.Extensions.Tests
}
private interface IFoo { }
private interface IFoo<T> : IFoo { }
private interface IFoo<T, M> : IFoo<T> { }
private class Foo : IFoo { }
private class Foo<T> : IFoo { }
private class Foo<T, M> : IFoo<T> { }
private class FooInt : IFoo<int> { }
private class FooStringInt : IFoo<string, int> { }
private class Foo2 : Foo { }
[Test]
public void InhertisFromTest()
{
Assert.That(typeof(Foo).InheritsFrom<IFoo>());
Assert.That(typeof(FooInt).InheritsFrom<IFoo>());
Assert.That(typeof(FooInt).InheritsFrom(typeof(IFoo<>)));
Assert.That(typeof(FooInt).InheritsFrom<IFoo<int>>());
Assert.That(typeof(FooInt).InheritsFrom<IFoo<string>>());
Assert.That(typeof(FooInt).InheritsFrom(typeof(IFoo<,>)));
Assert.That(typeof(FooStringInt).InheritsFrom(typeof(IFoo<,>)));
Assert.That(typeof(FooStringInt).InheritsFrom<IFoo<string, int>>());
Assert.That(typeof(Foo<int, string>).InheritsFrom<IFoo<string>>());
Assert.That(typeof(Foo2).InheritsFrom<Foo>());
Assert.That(typeof(Foo2).InheritsFrom<IFoo>());
}
[Test()]
public void InvokeMethodRetTest()
{