Search code examples
postsharp

PostSharp: How to prevent double aspect invoking when calling base method?


For example:

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

Problem is that base.Func() leads to double aspect invoking. Is it possible to prevent this?


Solution

  • This is probably the best way. I just ignore logging on overridden methods.

        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();
        }