¿Cómo obtener una lista de propiedades con un atributo dado?

Tengo un tipo, t , y me gustaría obtener una lista de las propiedades públicas que tienen el atributo MyAttribute . El atributo está marcado con AllowMultiple = false , así:

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

Actualmente, lo que tengo es esto, pero estoy pensando que hay una mejor manera:

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

¿Cómo puedo mejorar esto? Mis disculpas si esto es un duplicado, hay un montón de hilos de reflexión por ahí … parece que es un tema bastante candente.

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

Esto evita tener que materializar cualquier instancia de atributo (es decir, es más barato que GetCustomAttribute[s]() .

La solución que uso más se basa en la respuesta de Tomas Petricek. Por lo general, quiero hacer algo con el atributo y la propiedad.

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

Hasta donde yo sé, no hay una mejor manera en términos de trabajar con la biblioteca Reflection de una manera más inteligente. Sin embargo, podría usar LINQ para hacer que el código sea un poco más agradable:

 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' 

Creo que esto te ayuda a estructurar el código de una manera más legible.

Siempre hay LINQ:

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

Si maneja regularmente los Atributos en Reflection, es muy, muy práctico definir algunos métodos de extensión. Lo verás en muchos proyectos. Este es uno que a menudo tengo:

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

que puedes usar como typeof(Foo).HasAttribute();

Otros proyectos (por ejemplo, StructureMap) tienen clases ReflectionHelper completas que usan árboles de Expression para tener una syntax fina para la identidad, por ejemplo, PropertyInfos. El uso se ve así:

 ReflectionHelper.GetProperty(x => x.MyProperty).HasAttribute() 

Además de las respuestas anteriores: es mejor utilizar el método Any() lugar de verificar la longitud de la colección:

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

El ejemplo en dotnetfiddle: https://dotnetfiddle.net/96mKep

la mejor manera:

 //if (attributes.Length == 1) if (attributes.Length != 0)