When using custom attributes in .Net, one of the most common tasks is to query a member for any custom attributes that are applied. The MemberInfo class has a GetCustomAttributes method for just this purpose.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
This is fairly straightforward reflection code that loops through all of the public properties on
ClassWithAttribute and returns the names of any that have the
ExampleAttribute applied. In the example shown, on line 29 the
properties variable will be a list containing the words “Name” and “Age”.
But what happens if we use a class derived from
1 2 3 4 5 6 7 8
Perhaps surprisingly, the
properties variable on line 7 contains the single word “Age”. This surprised me since I’m supplying
true as the second parameter to
GetCustomAttributes() on line 21 of the first example. When the second parameter is true, the member’s inheritance chain should be searched for attributes. So why didn’t it find the
ExampleAttribute declared in
ClassWithAttribute? The answer is in the documentation, although I missed it the first few times I read it (emphasis mine):
inherit: true to search this member’s inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks.
The second parameter to
GetCustomAttributes() is ignored if the method is being called on a property or an event (we have a property in this case). Luckily the “Remarks” section of the documentation has a solution (emphasis mine):
This method ignores the inherit parameter for properties and events. To search the inheritance chain for attributes on properties and events, use the appropriate overloads of the Attribute.GetCustomAttributes method.
So in this case we can simply replace line 21 in
AttributeChecker.PropertiesWithAttribute() with the following:
Now running the code for
DerivedClassWithAttribute will correctly return both “Name” and “Age”. A simple change, but something that tripped me up for a while none the less.