【问题标题】:Generating and serialising metadata at compile time using PostSharp使用 PostSharp 在编译时生成和序列化元数据
【发布时间】:2013-01-13 16:47:54
【问题描述】:

我正在尝试做一些我认为应该直截了当且简单易行的事情,但就我的一生而言,我无法让它发挥作用。使用 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 { }

在此先感谢您的帮助,非常感谢,这对使我的头发在头上的寿命比在手上的时间长:)

【问题讨论】:

    标签: c# .net serialization reflection postsharp


    【解决方案1】:

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

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

    【讨论】:

    • 感谢 Gael,那么是什么提示 RuntimeInitialize 被调用?在我检查这个共享存储库之前,有没有办法强制调用它?
    • 另外,为什么 CompileTimeInitialize 似乎没有在 TypeLevelAspect 上执行 - 或者为什么我在测试中看到 11 而不是 9?
    • RuntimeInitialize 在切面执行前通过静态构造函数调用,无法控制何时调用。 CompileTimeValidateCompileTimeInitialize 之后运行并覆盖您的字段值。
    猜你喜欢
    • 1970-01-01
    • 2017-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    相关资源
    最近更新 更多