PostSharp - 将方面应用于 mscorlib 但禁止修改我自己的调用 class

PostSharp - Applying aspect to mscorlib but prohibit modifying calls in my own class

我的方面:

[Serializable]
class DumbLogger : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Log.Print("Entry: ") + args.Method.Name;
        args.FlowBehavior = FlowBehavior.Continue;
    }
}

这就是我用来修改 mscorlib 中的调用并试图排除它们在我的 class 调用 LOG

中被修改的方法
    [assembly: MY_PROJECT.DumbLogger(
    AttributeTargetTypes = "MY_PROJECT.Log",
    AttributeExclude = true,
    AttributePriority = 1)]


    [assembly: MY_PROJECT.DumbLogger(
    AttributeTargetAssemblies = "mscorlib",
    AttributePriority = 2)]

但是..这没有用,因为如果我用 ILspy 反编译器查看我的日志 class,我可以看到对任何 class @ mscorlib.dll 的方法调用被修改,例如:

<>z__Aspects.<System.Object.ToString>b__v(text)

我想这样做的原因是因为当我进入方法时Log.Print它会产生一个Whosebug异常并会无限地调用它自己。

我已经知道可能会排除某些命名空间和 classes,例如来自 mscorlib 的字符串,但我有理由按照我描述的方式进行操作。

PostSharp 方面通常应用于声明(程序集、类型、方法、参数、字段等)。当您在外部方法上应用 MethodLevelAspectOnMethodBoundaryAspect 的基础 class)时,PostSharp 会转换调用站点(IL 中的 call 指令),但仍然会想到声明本身的方面。

目前无法通过呼叫站点进行过滤,这需要不同类型的方面 and/or 建议。因此,您在程序集上指定的 AttributeExclude=true 属性没有任何效果,因为它表示该方面不应应用于 Log 类型,而事实并非如此。

解决这种情况的常用技术是使用 ThreadStatic 变量来中断递归循环,如下面的代码所示:

[Serializable]
class DumbLogger : OnMethodBoundaryAspect
{
    [ThreadStatic] private static bool logging;

    public override void OnEntry(MethodExecutionArgs args)
    {
        if (logging)
            return;

        try
        {
            logging = true;
            Log.Print("Entry: " + args.Method.Name);
            args.FlowBehavior = FlowBehavior.Continue;
        }
        finally
        {
            logging = false;
        }
    }
}

另请注意,MethodInterceptionOnMethodBoundary 方面是唯一适用于外部程序集的方面。