Check if a class is derived from a generic class

前端 未结 16 1663
太阳男子
太阳男子 2020-11-22 09:57

I have a generic class in my project with derived classes.

public class GenericClass : GenericInterface
{
}

public class Test : GenericCla         


        
16条回答
  •  南方客
    南方客 (楼主)
    2020-11-22 10:19

    Building on the excellent answer above by fir3rpho3nixx and David Schmitt, I have modified their code and added the ShouldInheritOrImplementTypedGenericInterface test (last one).

        /// 
        /// Find out if a child type implements or inherits from the parent type.
        /// The parent type can be an interface or a concrete class, generic or non-generic.
        /// 
        /// 
        /// 
        /// 
        public static bool InheritsOrImplements(this Type child, Type parent)
        {
            var currentChild = parent.IsGenericTypeDefinition && child.IsGenericType ? child.GetGenericTypeDefinition() : child;
    
            while (currentChild != typeof(object))
            {
                if (parent == currentChild || HasAnyInterfaces(parent, currentChild))
                    return true;
    
                currentChild = currentChild.BaseType != null && parent.IsGenericTypeDefinition && currentChild.BaseType.IsGenericType
                                    ? currentChild.BaseType.GetGenericTypeDefinition()
                                    : currentChild.BaseType;
    
                if (currentChild == null)
                    return false;
            }
            return false;
        }
    
        private static bool HasAnyInterfaces(Type parent, Type child)
        {
            return child.GetInterfaces().Any(childInterface =>
                {
                    var currentInterface = parent.IsGenericTypeDefinition && childInterface.IsGenericType
                        ? childInterface.GetGenericTypeDefinition()
                        : childInterface;
    
                    return currentInterface == parent;
                });
    
        }
    
        [Test]
        public void ShouldInheritOrImplementNonGenericInterface()
        {
            Assert.That(typeof(FooImplementor)
                .InheritsOrImplements(typeof(IFooInterface)), Is.True);
        }
    
        [Test]
        public void ShouldInheritOrImplementGenericInterface()
        {
            Assert.That(typeof(GenericFooBase)
                .InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
        }
    
        [Test]
        public void ShouldInheritOrImplementGenericInterfaceByGenericSubclass()
        {
            Assert.That(typeof(GenericFooImplementor<>)
                .InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
        }
    
        [Test]
        public void ShouldInheritOrImplementGenericInterfaceByGenericSubclassNotCaringAboutGenericTypeParameter()
        {
            Assert.That(new GenericFooImplementor().GetType()
                .InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
        }
    
        [Test]
        public void ShouldNotInheritOrImplementGenericInterfaceByGenericSubclassNotCaringAboutGenericTypeParameter()
        {
            Assert.That(new GenericFooImplementor().GetType()
                .InheritsOrImplements(typeof(IGenericFooInterface)), Is.False);
        }
    
        [Test]
        public void ShouldInheritOrImplementNonGenericClass()
        {
            Assert.That(typeof(FooImplementor)
                .InheritsOrImplements(typeof(FooBase)), Is.True);
        }
    
        [Test]
        public void ShouldInheritOrImplementAnyBaseType()
        {
            Assert.That(typeof(GenericFooImplementor<>)
                .InheritsOrImplements(typeof(FooBase)), Is.True);
        }
    
        [Test]
        public void ShouldInheritOrImplementTypedGenericInterface()
        {
            GenericFooImplementor obj = new GenericFooImplementor();
            Type t = obj.GetType();
    
            Assert.IsTrue(t.InheritsOrImplements(typeof(IGenericFooInterface)));
            Assert.IsFalse(t.InheritsOrImplements(typeof(IGenericFooInterface)));
        } 
    

提交回复
热议问题