Search code examples
c#postsharp

Postsharp - Introduced virtual method is called instead overriden method


Aspect looks like this

[Serializable] 
[IntroduceInterface(typeof(ISomeMethod), OverrideAction = InterfaceOverrideAction.Ignore)] 
public class MyAspect: InstanceLevelAspect, ISomeMethod 
{ 
    [IntroduceMember(IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)] 
    public string SomeMethod() 
    { 
        throw new NotImplementedException(); 
    }

    [OnMethodInvokeAdvice, MulticastPointcut(Targets = MulticastTargets.Method, Attributes = MulticastAttributes.Public)] 
    public void OnInvoke(MethodInterceptionArgs args) 
    { 
        var something = args.Instance as ISomeMethod;

        //here is problem
        string str = something.SomeMethod();

        args.Proceed(); 
    } 
}

When i check it in dotPeek, SomeMethod is introduced and is virtual. Aspect is applied to base class that is in different project as child classes. Problem is when i override this method and OnInvoke interceptor is called, SomeMethod in aspect is actually called with NotImplementedException instead of overriden method. Debugger confirmed i have right instance in args.Instance. How is this possible? Thanks for answer.


Solution

  • This is a bug which is going to be solved in future version of PostSharp solved since PostSharp 4.2.22/4.3.5.

    The rest of the original answer:

    But there is a workaround.

    Let me visualize the code described in the question. The base class in project A would look like this:

    [MyAspect]
    public abstract class BaseClass
    {
        public void InterceptedMethod(string message)
        {
        }
    }
    

    The child class in project B reproducing the bug would look like this:

    public class ChildClass : BaseClass
    {
        public override string SomeMethod()
        {
            return "";
        }
    }
    

    The workaround for now is to implement the interface method instead of overriding it.

    public class ChildClass : BaseClass, ISomeMethod
    {
        public string SomeMethod()
        {
            return "";
        }
    }