Getting all types that implement an interface

前端 未结 17 1227
不思量自难忘°
不思量自难忘° 2020-11-22 00:34

Using reflection, how can I get all types that implement an interface with C# 3.0/.NET 3.5 with the least code, and minimizing iterations?

This is what I want to re-

17条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-22 01:15

    There are many valid answers already but I'd like to add anther implementation as a Type extension and a list of unit tests to demonstrate different scenarios:

    public static class TypeExtensions
    {
        public static IEnumerable GetAllTypes(this Type type)
        {
            var typeInfo = type.GetTypeInfo();
            var allTypes = GetAllImplementedTypes(type).Concat(typeInfo.ImplementedInterfaces);
            return allTypes;
        }
    
        private static IEnumerable GetAllImplementedTypes(Type type)
        {
            yield return type;
            var typeInfo = type.GetTypeInfo();
            var baseType = typeInfo.BaseType;
            if (baseType != null)
            {
                foreach (var foundType in GetAllImplementedTypes(baseType))
                {
                    yield return foundType;
                }
            }
        }
    }
    

    This algorithm supports the following scenarios:

    public static class GetAllTypesTests
    {
        public class Given_A_Sample_Standalone_Class_Type_When_Getting_All_Types
            : Given_When_Then_Test
        {
            private Type _sut;
            private IEnumerable _expectedTypes;
            private IEnumerable _result;
    
            protected override void Given()
            {
                _sut = typeof(SampleStandalone);
    
                _expectedTypes =
                    new List
                    {
                        typeof(SampleStandalone),
                        typeof(object)
                    };
            }
    
            protected override void When()
            {
                _result = _sut.GetAllTypes();
            }
    
            [Fact]
            public void Then_It_Should_Return_The_Right_Type()
            {
                _result.Should().BeEquivalentTo(_expectedTypes);
            }
        }
    
        public class Given_A_Sample_Abstract_Base_Class_Type_When_Getting_All_Types
            : Given_When_Then_Test
        {
            private Type _sut;
            private IEnumerable _expectedTypes;
            private IEnumerable _result;
    
            protected override void Given()
            {
                _sut = typeof(SampleBase);
    
                _expectedTypes =
                    new List
                    {
                        typeof(SampleBase),
                        typeof(object)
                    };
            }
    
            protected override void When()
            {
                _result = _sut.GetAllTypes();
            }
    
            [Fact]
            public void Then_It_Should_Return_The_Right_Type()
            {
                _result.Should().BeEquivalentTo(_expectedTypes);
            }
        }
    
        public class Given_A_Sample_Child_Class_Type_When_Getting_All_Types
            : Given_When_Then_Test
        {
            private Type _sut;
            private IEnumerable _expectedTypes;
            private IEnumerable _result;
    
            protected override void Given()
            {
                _sut = typeof(SampleChild);
    
                _expectedTypes =
                    new List
                    {
                        typeof(SampleChild),
                        typeof(SampleBase),
                        typeof(object)
                    };
            }
    
            protected override void When()
            {
                _result = _sut.GetAllTypes();
            }
    
            [Fact]
            public void Then_It_Should_Return_The_Right_Type()
            {
                _result.Should().BeEquivalentTo(_expectedTypes);
            }
        }
    
        public class Given_A_Sample_Base_Interface_Type_When_Getting_All_Types
            : Given_When_Then_Test
        {
            private Type _sut;
            private IEnumerable _expectedTypes;
            private IEnumerable _result;
    
            protected override void Given()
            {
                _sut = typeof(ISampleBase);
    
                _expectedTypes =
                    new List
                    {
                        typeof(ISampleBase)
                    };
            }
    
            protected override void When()
            {
                _result = _sut.GetAllTypes();
            }
    
            [Fact]
            public void Then_It_Should_Return_The_Right_Type()
            {
                _result.Should().BeEquivalentTo(_expectedTypes);
            }
        }
    
        public class Given_A_Sample_Child_Interface_Type_When_Getting_All_Types
            : Given_When_Then_Test
        {
            private Type _sut;
            private IEnumerable _expectedTypes;
            private IEnumerable _result;
    
            protected override void Given()
            {
                _sut = typeof(ISampleChild);
    
                _expectedTypes =
                    new List
                    {
                        typeof(ISampleBase),
                        typeof(ISampleChild)
                    };
            }
    
            protected override void When()
            {
                _result = _sut.GetAllTypes();
            }
    
            [Fact]
            public void Then_It_Should_Return_The_Right_Type()
            {
                _result.Should().BeEquivalentTo(_expectedTypes);
            }
        }
    
        public class Given_A_Sample_Implementation_Class_Type_When_Getting_All_Types
            : Given_When_Then_Test
        {
            private Type _sut;
            private IEnumerable _expectedTypes;
            private IEnumerable _result;
    
            protected override void Given()
            {
                _sut = typeof(SampleImplementation);
    
                _expectedTypes =
                    new List
                    {
                        typeof(SampleImplementation),
                        typeof(SampleChild),
                        typeof(SampleBase),
                        typeof(ISampleChild),
                        typeof(ISampleBase),
                        typeof(object)
                    };
            }
    
            protected override void When()
            {
                _result = _sut.GetAllTypes();
            }
    
            [Fact]
            public void Then_It_Should_Return_The_Right_Type()
            {
                _result.Should().BeEquivalentTo(_expectedTypes);
            }
        }
    
        public class Given_A_Sample_Interface_Instance_Type_When_Getting_All_Types
            : Given_When_Then_Test
        {
            private Type _sut;
            private IEnumerable _expectedTypes;
            private IEnumerable _result;
    
            class Foo : ISampleChild { }
    
            protected override void Given()
            {
                var foo = new Foo();
                _sut = foo.GetType();
    
                _expectedTypes =
                    new List
                    {
                        typeof(Foo),
                        typeof(ISampleChild),
                        typeof(ISampleBase),
                        typeof(object)
                    };
            }
    
            protected override void When()
            {
                _result = _sut.GetAllTypes();
            }
    
            [Fact]
            public void Then_It_Should_Return_The_Right_Type()
            {
                _result.Should().BeEquivalentTo(_expectedTypes);
            }
        }
    
        sealed class SampleStandalone { }
        abstract class SampleBase { }
        class SampleChild : SampleBase { }
        interface ISampleBase { }
        interface ISampleChild : ISampleBase { }
        class SampleImplementation : SampleChild, ISampleChild { }
    }
    

提交回复
热议问题