使用PostSharp在编译时生成和序列化元数据

时间:2013-01-29 23:59:01

标签: c# .net serialization reflection postsharp

我正在尝试做一些我认为应该直截了当且容易做的事情,但对于我的生活,我无法让它发挥作用。使用PostSharp,我想创建一个应用于类(或接口)定义的方面,并且该方面在编译时反映它已应用的类型,然后将该反射信息存储在变量中以备提取运行时间。

我知道CompileTimeInitialize函数应该用于生成反射信息并将其保存到变量中。这一切都被序列化了。但是,我无法在运行时获取存储的信息。 RuntimeInitialize可以看到变量及其中的数据,但是当我使用GetCustomAttributes从我的代码中的其他类型获取属性时,该属性为空。

以下是我目前的一些代码:

[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?)            
    }

}

以下是我尝试使用的控制台应用程序来提取数字:

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 { }

在此先感谢您的帮助,我们非常感谢并且让我的头发在我的头上比在我的头上更持久:)

1 个答案:

答案 0 :(得分:1)

当您使用Type.GetCustomAttributes时,您需要CLR根据存储在元数据中的定义构建自定义属性的新实例,即通过调用构造函数并设置字段和属性。因此,您没有获得PostSharp创建和初始化的实例,而是一个全新的实例。

如果要访问PostSharp实例,则应使用RuntimeInitialize将此实例存储在某种方面实例的共享存储库中,然后从代码中访问它们。请注意,PostSharp会懒惰地运行RuntimeInitialize,因此在初始化之前您将无法访问该实例。