PostSharp:调用基本方法时如何防止双向调用?

时间:2019-05-17 13:02:23

标签: postsharp

例如:

class BaseClass : IDisposable {
   [LogMethod]
   public BaseClass() {
   }

   [LogMethod] // This is OnMethodBoundaryAspect with MulticastInheritance.Strict
   public virtual void Dispose() { // overridden method
   }
}

class SubClass : BaseClass {
    public SubClass() : base() { // this doesn't lead to double LogMethod invoking
    }

    public override void Dispose() { // overriding method
      base.Func(); // this leads to double LogMethod invoking
    }
}

问题是base.Func()导致双向调用。有可能防止这种情况吗?

2 个答案:

答案 0 :(得分:1)

不更改代码或更改方面本身是不可能的。

原因是PostSharp转换方法代码。它将对方面的调用添加到BaseClass.Dispose的方法主体和SubClass.Dispose的方法主体中。由于BaseClass.Dispose会调用SubClass.Dispose,因此这两个方面都会得到执行。

要在从BaseClass.Dispose调用SubClass.Dispose时禁用方面,您需要将有关其调用者的信息传递给base方法。在不更改代码的情况下(这会破坏方面的目的),可以通过更改方面使用AsyncLocal[ThreadStatic]在方面实例之间传递状态。

答案 1 :(得分:0)

这可能是最好的方法。我只是忽略登录重写的方法。

    void IInstanceScopedAspect.RuntimeInitializeInstance() {
        IsEnabled = !IsOverridden( method, instance );
    }

    private static bool IsOverridden(MethodBase method, object instance) {
        if (method is MethodInfo method_) return instance.GetType().HasOverridingMethod( method_ );
        return false;
    }


    public static bool HasOverridingMethod(this Type type, MethodInfo baseMethod) {
        return type.GetOverridingMethod( baseMethod ) != null;
    }
    public static MethodInfo GetOverridingMethod(this Type type, MethodInfo baseMethod) {
        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod;
        return type.GetMethods( flags ).FirstOrDefault( i => baseMethod.IsBaseMethodOf( i ) );
    }
    private static bool IsBaseMethodOf(this MethodInfo baseMethod, MethodInfo method) {
        return baseMethod.DeclaringType != method.DeclaringType && baseMethod == method.GetBaseDefinition();
    }