web-dev-qa-db-fra.com

Comment obtenir une liste de propriétés avec un attribut donné?

J'ai un type, t, et j'aimerais obtenir une liste des propriétés publiques qui ont l'attribut MyAttribute. L'attribut est marqué avec AllowMultiple = false, comme ça:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]

Actuellement, ce que j'ai est la suivante, mais je pense qu'il existe un meilleur moyen:

foreach (PropertyInfo prop in t.GetProperties())
{
    object[] attributes = prop.GetCustomAttributes(typeof(MyAttribute), true);
    if (attributes.Length == 1)
    {
         //Property with my custom attribute
    }
}

Comment puis-je améliorer cela? Toutes mes excuses, s’il s’agit d’un doublon, il y a une tonne de fils de réflexion ... cela semble être un sujet brûlant.

197
wsanville
var props = t.GetProperties().Where(
                prop => Attribute.IsDefined(prop, typeof(MyAttribute)));

Cela évite d’avoir à matérialiser des instances d’attributs (c’est-à-dire que cela revient moins cher que GetCustomAttribute[s]() ").

363
Marc Gravell

La solution que je finis par utiliser le plus est basée sur la réponse de Tomas Petricek. Je veux généralement faire quelque chose avec les deux l'attribut et la propriété.

var props = from p in this.GetType().GetProperties()
            let attr = p.GetCustomAttributes(typeof(MyAttribute), true)
            where attr.Length == 1
            select new { Property = p, Attribute = attr.First() as MyAttribute};
42
wsanville

Autant que je sache, il n'y a pas de meilleure façon de travailler de manière plus intelligente avec la bibliothèque Reflection. Cependant, vous pourriez utiliser LINQ pour rendre le code un peu plus agréable:

var props = from p in t.GetProperties()
            let attrs = p.GetCustomAttributes(typeof(MyAttribute), true)
            where attrs.Length != 0 select p;

// Do something with the properties in 'props'

Je pense que cela vous aide à structurer le code de manière plus lisible.

33
Tomas Petricek

Il y a toujours LINQ:

t.GetProperties().Where(
    p=>p.GetCustomAttributes(typeof(MyAttribute), true).Length != 0)
13
P Daddy

Si vous traitez régulièrement des attributs dans Reflection, il est très, très pratique de définir certaines méthodes d'extension. Vous verrez cela dans de nombreux projets. Celui-ci est celui que j'ai souvent:

public static bool HasAttribute<T>(this ICustomAttributeProvider provider) where T : Attribute
{
  var atts = provider.GetCustomAttributes(typeof(T), true);
  return atts.Length > 0;
}

que vous pouvez utiliser comme typeof(Foo).HasAttribute<BarAttribute>();

D'autres projets (StructureMap, par exemple) ont des classes ReflectionHelper à part entière qui utilisent des arbres d'expression pour avoir une syntaxe fine d'identification, par exemple. PropertyInfos. L'utilisation ressemble alors à ça:

ReflectionHelper.GetProperty<Foo>(x => x.MyProperty).HasAttribute<BarAttribute>()
5
flq

En plus des réponses précédentes: il vaut mieux utiliser la méthode Any() au lieu de vérifier la longueur de la collection:

propertiesWithMyAttribute = type.GetProperties()
  .Where(x => x.GetCustomAttributes(typeof(MyAttribute), true).Any());

L’exemple de dotnetfiddle: https://dotnetfiddle.net/96mKep

2
feeeper