2016-02-12 18 views
5

Nel new Reflection API, le proprietà TypeInfo.Declared* sono il modo giusto per accedere ai membri (campi, proprietà, metodi, ecc.) Dichiarati su un tipo. Tuttavia, queste proprietà non includono membri ereditati da una classe base.Come ottenere membri dichiarati e ereditati da TypeInfo

I vecchi metodi TypeInfo.GetRuntime*() restituiscono sia membri dichiarati che ereditati, ma non sono disponibili su tutte le piattaforme, incluso .NET Core.

Come si ottiene un elenco dei membri dichiarati e ereditati con la nuova API?

risposta

16

ho scritto una serie di piccoli metodi di estensione che forniscono questa funzionalità:

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(); 
     } 
    } 
} 

Questo dovrebbe essere super facile da usare. Ad esempio, chiamando typeInfo.GetAllProperties(), si restituirà tutto il DeclaredProperties del tipo corrente e qualsiasi tipo di base, fino alla struttura di ereditarietà.

Non impongo alcun ordine qui, quindi se è necessario enumerare i membri in un ordine specifico, potrebbe essere necessario modificare la logica.


alcuni semplici test per dimostrare:

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; } 
} 

Questi metodi di estensione sono compatibili sia con 4.5+ NET desktop e .NET Nucleo.