Get PropertyDescriptorCollection filtered by custom Attribute

2.1k Views Asked by At

I need to obtain a PropertyDescriptorCollection with all properties that are decorated with a custom attribute. The problem is that TypeDescriptor.GetProperties can only filter by an exact matching of all Attribute's properties, so if I want to get all properties no matter how attribute's properties are set, I would have to cover all the possibilities in the filter array.

Here is the code for my attribue:

[AttributeUsage(AttributeTargets.Property)]
class FirstAttribute : Attribute
{
    public bool SomeFlag { get; set; }
}

And a class with decorated properties:

class Foo
{
    [First]
    public string SomeString { get; set; }

    [First(SomeFlag = true)]
    public int SomeInt { get; set; }
}

And main:

static void Main(string[] args)
{
    var firstPropCollection = TypeDescriptor.GetProperties(typeof(Foo), new Attribute[] {new FirstAttribute()});
    Console.WriteLine("First attempt: Filtering by passing an array with a new FirstAttribute");
    foreach (PropertyDescriptor propertyDescriptor in firstPropCollection)
    {
        Console.WriteLine(propertyDescriptor.Name);
    }

    Console.WriteLine();
    Console.WriteLine("Second attempt: Filtering by passing an an array with a new FirstAttribute with object initialization");
    var secondPropCollection = TypeDescriptor.GetProperties(typeof(Foo), new Attribute[] { new FirstAttribute {SomeFlag = true} });
    foreach (PropertyDescriptor propertyDescriptor in secondPropCollection)
    {
        Console.WriteLine(propertyDescriptor.Name);
    }

    Console.WriteLine();
    Console.WriteLine("Third attempt: I am quite ugly =( ... but I work!");
    var thirdCollection = TypeDescriptor.GetProperties(typeof(Foo)).Cast<PropertyDescriptor>()
        .Where(p => p.Attributes.Cast<Attribute>().Any(a => a.GetType() == typeof(FirstAttribute)));
    foreach (PropertyDescriptor propertyDescriptor in thirdCollection)
    {
        Console.WriteLine(propertyDescriptor.Name);
    }

    Console.ReadLine();
}

So far, the only way I have made it worked is the third attempt, I wonder if there is a more intuitive and elegant way.

The output is the following:

enter image description here

As you can see I can only manage to get both properties with the last attempt.

1

There are 1 best solutions below

4
On

I am not really sure that I understand the problem... You want all properties that have a specific attribute regardless of this attributes value?

class Program
{
    static void Main(string[] args)
    {
        var props = typeof(Foo).GetProperties();
        var filtered = props
            .Where(x => x.GetCustomAttributes(typeof(FirstAttribute), false).Length > 0)
            .ToList();
        var propertyDescriptor = TypeDescriptor.GetProperties(typeof(Foo))
            .Find(filtered[0].Name, false);
    }
}
class Foo
{
    [First]
    public string SomeString { get; set; }

    [First(SomeFlag = true)]
    public int SomeInt { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
class FirstAttribute : Attribute
{
    public bool SomeFlag { get; set; }
}