Recently a colleague of mine pointed to a strange behavior in .NET Reflection that pushed me doing a lot of additional investigations and finding out a very serious limitation that might raise a lot of issues if not being taken into account.
When you declare property as “virtual” beware that custom attributes won’t be fetched for the derived one if the property is being overrided.
This can be easily tested. First you need creating two custom attributes that will target two cases: virtual property and virtual method.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class MyPropertyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyMethodAttribute : Attribute
{
}
Now you can create two classes: “BaseClass” that will contain a single virtual property and single virtual method and “DerivedClass” that will override both members.
public class BaseClass
{
private string _PropertyVirtual;
[MyProperty]
public virtual string PropertyVirtual
{
get { return _PropertyVirtual; }
set { _PropertyVirtual = value; }
}
[MyMethod]
public virtual void MethodVirtual()
{
}
}
public class DerivedClass : BaseClass
{
public override string PropertyVirtual
{
get { return base.PropertyVirtual; }
set { base.PropertyVirtual = value; }
}
public override void MethodVirtual()
{
base.MethodVirtual();
}
}
The problem starts when you try fetching custom attributes for “PropertyVirtual” from within a DerivedClass because you will never get them using PropertyInfo.GetCustomAttributes method call. Here’s a sample Console Application to ensure the limitation is alive:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Checking virtual property attributes:\r\n");
Console.WriteLine(
"BaseClass.PropertyVirtual attributes count: {0}",
typeof(BaseClass).GetProperty("PropertyVirtual").GetCustomAttributes(true).Length);
Console.WriteLine(
"DerivedClass.PropertyVirtual attributes count: {0}",
typeof(DerivedClass).GetProperty("PropertyVirtual").GetCustomAttributes(true).Length);
Console.WriteLine("\r\nChecking virtual method attributes:\r\n");
Console.WriteLine(
"BaseClass.MethodVirtual attributes count: {0}",
typeof(BaseClass).GetMethod("MethodVirtual").GetCustomAttributes(true).Length);
Console.WriteLine(
"DerivedClass.MethodVirtual attributes count: {0}",
typeof(DerivedClass).GetMethod("MethodVirtual").GetCustomAttributes(true).Length);
Console.ReadLine();
}
Upon running this sample you should see the following results:
Checking virtual property attributes:
BaseClass.PropertyVirtual attributes count: 1
DerivedClass.PropertyVirtual attributes count: 0
Checking virtual method attributes:
BaseClass.MethodVirtual attributes count: 1
DerivedClass.MethodVirtual attributes cound: 1
As you can ensure there are no custom attributes returned for overrided virtual property while the expected result is fetched for overrided virtual method.
You can easily find what is happening under the hood if switching to MSIL representation of the classes coded above. Here’s how the “BaseClass” attribute usage looks like:

As you can see on the IL level “MethodVirtual” declares “MyMethodAttribute” instance right within its own body. The same goes for “PropertyVirtual” – a getter, a setter and attribute declaration.
However both members look like the following when derived:

While “MethodVirtual” still refers to “base.MethodVirtual” and theoretically can invoke attribute declaration,
note that the following overriding will still work for methods:
public class DerivedClass : BaseClass
{
public override string PropertyVirtual
{
get { return base.PropertyVirtual; }
set { base.PropertyVirtual = value; }
}
public override void MethodVirtual()
{
//base.MethodVirtual();
}
}
“PropertyVirtual” is no longer related to a base implementation. We have a completely new property definition that is wired with base getter and setter. But no custom attribute declaration!
This means that the default code written for MemberInfo class won’t be able fetching anything except empty object array.
There are two workarounds I found that help switching to another MS developer(s) work, custom attribute fetching seems to be completely different in the following approaches: TypeDescriptor and old-fashioned Attribute class.
Console.WriteLine(
"DerivedClass.PropertyVirtual attributes count: {0}",
Attribute.GetCustomAttributes(typeof(DerivedClass).GetProperty("PropertyVirtual"), typeof(MyPropertyAttribute)).Length);
The code above will be able to fetch and display custom attributes for a virtual property. Same can be achieved by means of property descriptors:
Console.WriteLine(
"DerivedClass.PropertyVirtual attributes count: {0}",
TypeDescriptor.GetProperties(typeof(DerivedClass))["PropertyVirtual"].Attributes[typeof(MyPropertyAttribute)] != null);
However the last one will have a great performance overhead in comparison with the “Attribute.GetCustomAttributes” usage.
I’ve tested the same issue with .NET 4.0 (beta 2) and it is still there. I really hope this article will help you detecting problems with your software and eliminating issues related to this very case.
You can find the source code for this article here: MetadataIssue
Like this:
Like Loading...