关于运行时初始化差异的PostSharp方面

时间:2015-07-31 11:36:48

标签: c# aop postsharp

我对PostSharp很新,所以请引导我找到正确的方向。

假设我有LoggingAspect:

    public class LoggingAspect : OnMethodBoundaryAspect
    {
        private ILog _log;

        private string _targetFullName;
}

第一个问题,如果我将_log声明为static成员,它是否会在所有LoggingAspect实例中共享?在方面内部使用静态变量是否常见?

现在我通过覆盖CompileTimeInitialize

来使用编译时初始化
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
{
    _log = LogManager.GetLogger(method.DeclaringType);
    _targetFullName = string.Format("{0}.{1}", method.DeclaringType.Name, method.Name);
}

这里我有点困惑,PostSharp在将我的方面序列化为托管资源时如何保持对logger实例的引用?

此外,我可以在运行时将_log变量:

public override void RuntimeInitialize(MethodBase method)
{
    _log = LogManager.GetLogger(method.DeclaringType);
}

我应该使用什么方法?编译时还是运行时?它会有什么不同吗?

1 个答案:

答案 0 :(得分:0)

您可以在方面类中使用静态字段,当然它将在方面的所有实例之间共享。

但是,大多数方面字段通常是实例字段。在编译项目期间可以计算某些字段的值(例如,示例中为 _targetFullName )。您可能希望在CompileTimeInitialize方法中初始化这些字段,以避免在运行时进行不必要的计算。

在编译时,PostSharp为应用方面的每个代码元素创建方面类的新实例。在CompileTimeInitialize对给定实例执行后,它将序列化为程序集受管资源。在应用程序运行时,方面实例被反序列化,并且所有先前计算的字段都将被恢复。

另一方面,对于某些字段,值只能在运行时计算,或者在运行时之前没有实际意义(例如示例中的 _log - 您希望在运行时记录,并且所有日志记录配置也在运行时可用)。您将这些字段标记为[NonSerialized],并在RuntimeInitialize方法中初始化它们的值。

在更复杂的场景中,您还可以为目标类的每个新实例创建一个新的方面实例。在这种情况下,您通常还会实现RuntimeInitializeInstance方法。

所有这些也在文档文章Understanding Aspect Lifetime and Scope中讨论过。

相关问题