2009-04-29 10 views
15

je demanderai à ce mal, mais peut/comment pouvez-vous trouver des champs sur une classe en elle-même ... par exemple ...C# Réflexion: Trouver des attributs sur un champ membre

public class HtmlPart { 
    public void Render() { 
    //this.GetType().GetCustomAttributes(typeof(OptionalAttribute), false); 
    } 
} 

public class HtmlForm { 
    private HtmlPart _FirstPart = new HtmlPart();  
    [Optional] //<-- how do I find that? 
    private HtmlPart _SecondPart = new HtmlPart(); 
} 

Ou peut-être que je Je fais juste cela de façon incorrecte ... Comment puis-je appeler une méthode et ensuite vérifier les attributs appliqués à elle-même?

En outre, à cause de la question - Je suis juste curieux de savoir s'il était possible de trouver des informations d'attribut sans savoir/accéder à la classe parente!

Répondre

12

Si je comprends bien votre question, je pense que ce que vous essayez de faire est impossible ...

Dans la méthode Render, vous voulez obtenir un attribut possible appliqué à l'objet. L'attribut appartient au champ _SecondPart witch appartient à la classe HtmlForm.

Pour cela vous devrez travailler pour passer l'objet d'appel à la méthode Render:

public class HtmlPart { 
     public void Render(object obj) { 
      FieldInfo[] infos = obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 

      foreach (var fi in infos) 
      { 
       if (fi.GetValue(obj) == this && fi.IsDefined(typeof(OptionalAttribute), true)) 
        Console.WriteLine("Optional is Defined"); 
      } 
     } 
    } 
+0

Remerciements - Cela semblait "possible", mais là encore, je me suis dit qu'il manquait juste assez pour que ça ne marche pas. – Hugoware

+2

Non, la méthode Render peut parfaitement accéder à typeof (HtmlForm) au lieu de obj.GetType(), alors vous n'avez plus besoin de l'obj. Bien sûr, si HtmlForm lui-même était privé, alors vous pourriez avoir besoin de le trouver à travers Assembly.GetExecutingAssembly(). GetTypes(). Où (t =>! T.IsGeneric &&! T.IsNested && t.FullName == "MyNamespace. HtmlForm ") ou quelque chose comme ça. – Timwi

5

Vous pouvez trouver des champs au sein d'une classe à l'aide Type.GetFields, et vous pouvez trouver des attributs appliqués à un champ à l'aide MemberInfo.GetCustomAttributes ou IsDefined - mais si vous avez besoin de trouver tous les champs d'un type particulier, vous allez devoir :

  • itérer sur tous les ensembles que vous souhaitez rechercher
  • itérer sur tous les types dans chaque assemblage
  • itérer sur tous les champs dans chaque type
  • Vérifier la présence d'attribut/absence pour chaque champ

Maintenant, si vous êtes vraiment essayer de savoir « est un attribut particulier appliqué à un champ dont la valeur est une référence à « ce » objet », alors que ça encore plus difficile - parce que vous devriez tout savoir sur chaque objet du système. Vous devez également garder à l'esprit qu'il peut y avoir deux champs ayant tous les deux la même valeur, c'est-à-dire référençant le même objet. L'objet serait-il considéré comme "optionnel" dans ce cas ou pas?

Fondamentalement, si l'objet doit avoir une propriété (par exemple facultative ou non), cela doit être une propriété de l'objet lui-même, et non du champ contenant la propriété.

Il se peut que j'interprète mal ce que vous essayez de faire, mais je doute que ce soit impossible ou du moins pas une bonne idée. Pourriez-vous expliquer l'image plus grande ici? Qu'est-ce que vous essayez vraiment de réaliser avec cet attribut?

+0

Merci pour la réponse - En ce moment, il est plus d'une expérience que toute autre chose. Je me demandais si c'était même possible, car c'était un moyen original d'essayer d'obtenir cette information. – Hugoware

10

Voici un exemple de donné un seul objet comment trouver si des champs publics ou privés sur cet objet ont une propriété spécifique:

var type = typeof(MyObject); 
foreach (var field in type.GetFields(BindingFlags.Public | 
      BindingFlags.NonPublic | BindingFlags.Instance)) 
{ 
    if (field.IsDefined(typeof(ObsoleteAttribute), true)) 
    { 
     Console.WriteLine(field.Name); 
    } 

} 

Pour la deuxième partie de votre question, vous pouvez vérifier si un attribut est defiend sur la méthode actuelle à l'aide:

MethodInfo.GetCurrentMethod().IsDefined(typeof(ObsoleteAttribute)); 

Modifier

Pour répondre à votre édition oui il i s possible sans connaître le type réel. La fonction suivante prend un paramètre de type et renvoie tous les champs qui ont un attribut donné. Quelqu'un quelque part va connaître le type que vous voulez rechercher, ou aura une instance du type que vous voulez rechercher. Sans cela vous auriez à faire comme Jon Skeet a dit qui est d'énumérer tous les objets dans un assemblage.

public List<FieldInfo> FindFields(Type type, Type attribute) 
    { 
     var fields = new List<FieldInfo>(); 
     foreach (var field in type.GetFields(BindingFlags.Public | 
          BindingFlags.NonPublic | 
          BindingFlags.Instance)) 
     { 
      if (field.IsDefined(attribute, true)) 
      { 
       fields.Add(field); 
      } 

     } 
     return fields; 
    } 
Questions connexes