I'm trying to do something which I feel should be straight forward and simple to do, yet for the life of me, I can't get it to work. Using PostSharp, I want to create an aspect that I apply to a class (or interface) definition and that aspect, at compile time, reflects the type that it has been applied to and then stores that reflection information in a variable ready for extraction at run time.
I know that the CompileTimeInitialize function should be used to generate the reflection information and save it to a variable. This all then gets serialised. However, I can't get the information stored out at run time. The RuntimeInitialize can see the variable and the data in it, but when I then get the attribute from the type elsewhere in my code using GetCustomAttributes, the attribute is empty.
Here is some of the code I have so far:
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Class, AllowMultiple = false, PersistMetaData = true)]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class MetadataAttribute : TypeLevelAspect {
public MetadataAttribute() { }
private int test;
public override bool CompileTimeValidate(Type type) {
this.test = 11;
return true;
}
public override void CompileTimeInitialize(Type type, AspectInfo aspectInfo) {
this.test = 9;
}
public override void RuntimeInitialize(Type type) {
// When I break here, I can see during debugging, that test is 11 (I would have expected 9 to be honest, but I suspect that CompileTimeInitialize is not executed for a TypeLevelAspect - unless I am mistaken?)
}
}
Here is the console application that I am trying to use to extract the number:
class Program {
static void Main(string[] args) {
var ma = typeof(Test).GetCustomAttribute<MetadataAttribute>();
var test = new Test();
var ma2 = test.GetType().GetCustomAttribute<MetadataAttribute>();
// When I break here, both ma and ma2 have test set to 0.
}
}
[Metadata]
public class Test { }
Thanks in advance for any help, it is much appreciated and goes a long way to making my hair last longer on my head than in my hands :)
When you are using Type.GetCustomAttributes
, you are requiring the CLR to build a new instance of custom attributes from their definition stored in metadata, i.e. by calling the constructor and setting fields and properties. Therefore, you are not getting the instance that PostSharp created and initialized, but a fully new instance.
If you want to access the PostSharp instance, you should use RuntimeInitialize
to store this instance in some kind of shared repository of aspect instances, then access them from code. Note that PostSharp runs RuntimeInitialize
lazily, so you won't be able to access your instance until it has been initialized.