views:

141

answers:

2

Hi

I have an aspect that writes something to the console on exception. I have a base class that throws an exception on its constructor, and a derived class that have the aspect on its constructor.

I would expect that the derived class aspect on constructor will catch the base class exception, but it dont.

Is this by design? Is this a bug? Or am I doing something wrong?

Here is sample code (Console Application):

[Serializable]
public class OnExceptionWriteAspect : OnMethodBoundaryAspect
{
    public override void OnException(MethodExecutionEventArgs eventArgs)
    {
        Console.WriteLine("Exception catched on Aspect.");
    }
}

public class BaseClass
{
    public BaseClass()
    {
        throw new Exception();
    }
}

public class DerivedClass : BaseClass
{
    [OnExceptionWriteAspect]
    public DerivedClass()
        : base()
    {

    }
}

public class Program
{
    static void Main(string[] args)
    {
        try
        {
            new DerivedClass();
        }
        catch
        {
            Console.WriteLine("Exception catched on Main.");
        }
    }
}

The output is:

Exception catched on Main.

A: 

If you look at the DerivedClass via reflector you see that the Aspect only wraps the DerivedClass's constructor.

public class DerivedClass : BaseClass
{
    // Methods
    public DerivedClass()
    {
        MethodExecutionEventArgs ~laosEventArgs~1;
        try
        {
            ~laosEventArgs~1 = new MethodExecutionEventArgs(<>AspectsImplementationDetails_1.~targetMethod~1, this, null);
            <>AspectsImplementationDetails_1.MyTest.OnExceptionWriteAspect~1.OnEntry(~laosEventArgs~1);
            if (~laosEventArgs~1.FlowBehavior != FlowBehavior.Return)
            {
                <>AspectsImplementationDetails_1.MyTest.OnExceptionWriteAspect~1.OnSuccess(~laosEventArgs~1);
            }
        }
        catch (Exception ~exception~0)
        {
            ~laosEventArgs~1.Exception = ~exception~0;
            <>AspectsImplementationDetails_1.MyTest.OnExceptionWriteAspect~1.OnException(~laosEventArgs~1);
            switch (~laosEventArgs~1.FlowBehavior)
            {
                case FlowBehavior.Continue:
                case FlowBehavior.Return:
                    return;
            }
            throw;
        }
        finally
        {
            <>AspectsImplementationDetails_1.MyTest.OnExceptionWriteAspect~1.OnExit(~laosEventArgs~1);
        }
    }
}

public BaseClass()
{
    throw new Exception();
}

If you want to handle Aspect Inheritance look at using MulticastAttributeUsage

Mark
+1  A: 

This is by design. There is no way to put an exception handler around the call to the base constructor. The MSIL code would not be verifiable.

Gael Fraiteur
Suppose i still want the functionality described above, without touch the base class code, is that possible somehow?
DxCK
Theoretically, it would be possible, but your assembly would not be verifiable any more. It does not mean that it would not run, but it would require full trust. You could do it by playing directly with PostSharp Core. PostSharp Laos does not allow it.
Gael Fraiteur