I wrote a set of small extension methods that provide this functionality:
public static class TypeInfoAllMemberExtensions
{
public static IEnumerable<ConstructorInfo> GetAllConstructors(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredConstructors);
public static IEnumerable<EventInfo> GetAllEvents(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredEvents);
public static IEnumerable<FieldInfo> GetAllFields(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredFields);
public static IEnumerable<MemberInfo> GetAllMembers(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredMembers);
public static IEnumerable<MethodInfo> GetAllMethods(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredMethods);
public static IEnumerable<TypeInfo> GetAllNestedTypes(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredNestedTypes);
public static IEnumerable<PropertyInfo> GetAllProperties(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredProperties);
private static IEnumerable<T> GetAll<T>(TypeInfo typeInfo, Func<TypeInfo, IEnumerable<T>> accessor)
{
while (typeInfo != null)
{
foreach (var t in accessor(typeInfo))
{
yield return t;
}
typeInfo = typeInfo.BaseType?.GetTypeInfo();
}
}
}
This should be super easy to use. Calling typeInfo.GetAllProperties()
, for example, will return all of the DeclaredProperties
of the current type and any base types, all the way up the inheritance tree.
I'm not imposing any ordering here, so if you need to enumerate members in a specific order, you may have to tweak the logic.
Some simple tests to demonstrate:
public class Test
{
[Fact]
public void Get_all_fields()
{
var fields = typeof(TestDerived).GetTypeInfo().GetAllFields();
Assert.True(fields.Any(f => f.Name == "FooField"));
Assert.True(fields.Any(f => f.Name == "BarField"));
}
[Fact]
public void Get_all_properties()
{
var properties = typeof(TestDerived).GetTypeInfo().GetAllProperties();
Assert.True(properties.Any(p => p.Name == "FooProp"));
Assert.True(properties.Any(p => p.Name == "BarProp"));
}
}
public class TestBase
{
public string FooField;
public int FooProp { get; set; }
}
public class TestDerived : TestBase
{
public string BarField;
public int BarProp { get; set; }
}
These extension methods are compatible with both desktop .NET 4.5+ and .NET Core.