I was playing with class inheritance AND attributes today, and found out quite a shocking truth (or maybe shocking design, whichever worse).
The truth is: member attributes are always inherited, whether you set the Inherited property in the AttributeUsageAttribute to true or false. This, of course, have some implication that needs to be resolved.
For your better understanding, please review the code below:
[AttributeUsage(AttributeTargets.All, Inherited = false)]
public class TestAttribute : Attribute
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
That is the code for the Attribute we're testing (TestAttribute). I've designed it to be attachable to anything (class, method, property, etc.) and not inheritable.
This attribute is set on the class code like the following:
[Test(Name = "Class Declaration")]
public class BaseClass
{
[Test(Name = "Field Declaration")]
public int id;
[Test(Name = "Property Declaration")]
public int Id
{
get { return id; }
set { id = value; }
}
[Test(Name = "Method Declaration")]
public void Function() { }
}I've put an attribute into the class and members. To test the inheritance, I've created a subclass that has nothing:
public class ChildClass : BaseClass { }
Through Reflection, I've been able to retrieve all members and attributes in the ChildClass.
private static void Main(string[] args)
{
Type type = typeof(ChildClass);
foreach (TestAttribute attribute in type.GetCustomAttributes(false))
Console.WriteLine(attribute.Name);
MemberInfo[] minfos = type.GetMembers();
foreach (MemberInfo info in minfos)
{
object[] attributes = info.GetCustomAttributes(false);
foreach (TestAttribute attribute in attributes)
Console.WriteLine(attribute.Name);
}
Console.ReadLine();
}And here's the result:

For those who are clueless, this means that you can still access the attributes on the derived class even though you have specifically set the Inherited positional parameter on the attribute to false. The only way to unset this inheritance is to declare an overriding member on the ChildClass.
But then, what if I wanted to override member AND still get an inheritable attribute. Should setting "Inherited = true" does the job? Well, apparently not.
public class ChildClass : BaseClass
{
public override void Function()
{
}
}I've modified the ChildClass to override one of the members of the BaseClass, changed the Inherited parameter on the attribute, and voila, here's what happens:

Boom! This means that the attribute is NOT inherited through overriding. So my current conclusion is the Inherited positional parameters does not work as expected OR there is something wrong with my attribute-getter code (through Reflection).
Anyone has an experience with this?
The end solution I would like to achieve is attribute compartmenting, where attributes from a class does not get propagated to its subclasses with as little code as possible (currently it's already possible, but requires shadowing inherited members with private visibility).