Coder Perfect

What is the best way to retrieve a list of properties with a specific attribute?

Problem

I’ve got a type, t, and I’d want to retrieve a list of public properties with the property MyAttribute. AllowMultiple = false is used to mark the attribute, as in:

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

This is what I currently have, but I believe there is a better way:

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

What can I do to make this better? Please accept my apologies if this is a duplicate; there are a plethora of reflection threads out there…it appears to be a popular topic.

Asked by wsanville

Solution #1

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

This removes the need to materialize any attribute instances (and hence is less expensive than GetCustomAttributes[s]) ().

Answered by Marc Gravell

Solution #2

Tomas Petricek’s answer is the one that I end up using the most. In most cases, I want to use both the attribute and the property.

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

Answered by wsanville

Solution #3

As far as I’m aware, there isn’t a better way to deal with the Reflection library in a more efficient manner. You could, however, use LINQ to make the code look a little nicer:

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'

This, I believe, aids you in structuring the code in a more legible manner.

Answered by Tomas Petricek

Solution #4

There’s always LINQ:

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

Answered by P Daddy

Solution #5

If you work with Attributes in Reflection on a frequent basis, it’s a good idea to define some extension methods. This is something you’ll notice in a lot of projects. This is a common occurrence for me:

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

which you can use as an example typeof (Foo). HasAttribute();

Other projects (such as StructureMap) provide full-fledged ReflectionHelper classes that leverage Expression trees to identify e.g. PropertyInfos with a fine syntax. The following is an example of how to use it:

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

Answered by flq

Post is based on https://stackoverflow.com/questions/2281972/how-to-get-a-list-of-properties-with-a-given-attribute