web-dev-qa-db-fra.com

Obtenir le type d'un MemberInfo avec réflexion

J'utilise la réflexion pour charger un treeview avec la structure de classe d'un projet. Chacun des membres d'une classe se voit attribuer un attribut personnalisé.

Je n'ai aucun problème à obtenir les attributs d'une classe à l'aide de MemberInfo.GetCustomAttributes() mais j'ai besoin d'un moyen de déterminer si un membre de la classe est une classe personnalisée et a ensuite besoin de s'analyser pour renvoyer les attributs personnalisés.

Jusqu'à présent, mon code est:

MemberInfo[] membersInfo = typeof(Project).GetProperties();

foreach (MemberInfo memberInfo in membersInfo)
{
    foreach (object attribute in memberInfo.GetCustomAttributes(true))
    {
        // Get the custom attribute of the class and store on the treeview
        if (attribute is ReportAttribute)
        {
            if (((ReportAttribute)attribute).FriendlyName.Length > 0)
            {
               treeItem.Items.Add(new TreeViewItem() { Header = ((ReportAttribute)attribute).FriendlyName });
            }
        }
        // PROBLEM HERE : I need to work out if the object is a specific type
        //                and then use reflection to get the structure and attributes.
    }
}

Existe-t-il un moyen simple d'obtenir le type cible d'une instance MemberInfo afin que je puisse le gérer correctement? J'ai l'impression de manquer quelque chose d'évident mais je tourne en rond à la minute.

24
GrandMasterFlush

GetProperties renvoie un tableau de PropertyInfo vous devez donc l'utiliser.
Il suffit alors d'utiliser la propriété PropertyType .

PropertyInfo[] propertyInfos = typeof(Project).GetProperties();

foreach (PropertyInfo propertyInfo in propertyInfos)
{
    // ...
    if(propertyInfo.PropertyType == typeof(MyCustomClass))
        // ...
}
10
Daniel Hilgarth

Je pense que vous pouvez obtenir de meilleures performances si vous utilisez cette méthode d'extension:

public static Type GetUnderlyingType(this MemberInfo member)
{
    switch (member.MemberType)
    {
        case MemberTypes.Event:
            return ((EventInfo)member).EventHandlerType;
        case MemberTypes.Field:
            return ((FieldInfo)member).FieldType;
        case MemberTypes.Method:
            return ((MethodInfo)member).ReturnType;
        case MemberTypes.Property:
            return ((PropertyInfo)member).PropertyType;
        default:
            throw new ArgumentException
            (
             "Input MemberInfo must be if type EventInfo, FieldInfo, MethodInfo, or PropertyInfo"
            );
    }
}

Devrait fonctionner pour tout MemberInfo, pas seulement PropertyInfo. Vous pouvez éviter MethodInfo de cette liste car ce n'est pas un type sous-jacent en soi (mais un type de retour).

Dans ton cas:

foreach (MemberInfo memberInfo in membersInfo)
{
    foreach (object attribute in memberInfo.GetCustomAttributes(true))
    {
        if (attribute is ReportAttribute)
        {
            if (((ReportAttribute)attribute).FriendlyName.Length > 0)
            {
               treeItem.Items.Add(new TreeViewItem() { Header = ((ReportAttribute)attribute).FriendlyName });
            }
        }

        //if memberInfo.GetUnderlyingType() == specificType ? proceed...
    }
}

Je me demande pourquoi cela n'a pas fait partie de BCL par défaut.

58
nawfal