Reflection + Linq to get all properties that has Attribute in Assembly

1.6k Views Asked by At

I'm trying to get all properties that has a custom attribute in the assembly. I did it this way but I'm doing it with two steps that does the same validation.

Ex:

abstract class XX

class Y1 : XX {
   [MyCustomAttribute(Value = "val A")]
   public int Something {get; set;}

}

class Y2 : XX {
   [MyCustomAttribute(Value = "val A")]
   public int Another {get; set;}

}

class Y3 : XX {
   [MyCustomAttribute(Value = "val B")]
   public int A1 {get; set;}

   [MyCustomAttribute(Value = "val C")]
   public int A2 {get; set;}

}

So the list with all property in the assembly that has it

Something
Another
A1
A2

I'm getting it with this linq

string attrFilter = "SomeValue";

var ts = this.GetType().Assembly.GetTypes().ToList().FindAll(c => typeof(XX).IsAssignableFrom(c) && !c.IsAbstract && !c.IsInterface);

var classes = from classe in ts
              where classe.GetProperties().ToList().FindAll(
                      property => property.GetCustomAttributes(typeof(MyCustomAttribute), false).ToList().FindAll(
                          att => typeof(MyCustomAttribute).IsAssignableFrom(att.GetType()) && (att as MyCustomAttribute).Value == attrFilter
                      ).Count > 0
                    ).Count > 0
              select classe;

this only give me the classes. So I need to extract the properties from each class

List<PropertyInfo> properties = new List<PropertyInfo>();
Parallel.ForEach(classes, classe => {
    var props = classe.GetProperties().ToList();
    var fks = from property in props
              where property.GetCustomAttributes(typeof(MyCustomAttribute), false).ToList().FindAll(
                          att => typeof(MyCustomAttribute).IsAssignableFrom(att.GetType()) && (att as MyCustomAttribute).Value == attrFilter
                      ).Count > 0
              select property;

    fks.ToList().ForEach(p => properties.Add(p));
});

As you can see, WHERE condition of the property linq is the same as the class query without the class list.

I was wondering if would be possible to extract the property from the first linq query

1

There are 1 best solutions below

1
On BEST ANSWER

Let's break it down.

Get all the types:

var types = System.AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany
    ( 
        a => a.GetTypes() 
    );

For all the types, get all the properties:

var properties = types.SelectMany
( 
    t => t.GetProperties() 
);

For all the properties, get those with the attribute you want:

var list = properties.Where
( 
    p => p.GetCustomAttributes(typeof(Attribute), true).Any() 
);

All together:

var list= System.AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany( a => a.GetTypes() )
    .SelectMany( t => t.GetProperties() )
    .Where
    ( 
        p => p.GetCustomAttributes(typeof(Attribute), true).Any() 
    );