2

I'm working with an application which is using Unity (v2.0) as part of Microsoft Enterprise Library. It is set up so you can add an attribute to the top of a method, and something will be done (tracing/logging/caching et all), before the method executes. Sample code below:

static void Main(string[] args)
{
    IUnityContainer myContainer = new UnityContainer()
        .AddNewExtension<Interception>()
        .RegisterType<IFoo, Foo>(
            new Interceptor<InterfaceInterceptor>(),
            new InterceptionBehavior<PolicyInjectionBehavior>()
        );
    IFoo myFoo = myContainer.Resolve<IFoo>();

    myFoo.fooMethodCall();
}

public class TraceAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new TraceCallHandler();
    }
}

public class TraceCallHandler : ICallHandler
{
    public int Order { get; set; }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        IMethodReturn methodReturn;
        //Do tracing/chaching/other funky stuff
        methodReturn = getNext()(input, getNext);       
        return methodReturn;
    }
}

public interface IFoo
{
    int fooMethodCall();
}

public class Foo : IFoo
{
    [Trace]
    public int fooMethodCall()
    {
        return 0;
    }
}

Now, there are two annoyances I have with the way this works, and one pretty serious problem. The first annoyance is the size of the stacktrace which is generated see here. Trying to debug a function which is 5 levels deep results in some hideous stacktraces which are very difficult to navigate.

The second annoyance is that when debugging using VS2010, it seems impossible to step into fooMethodCall. Trying to step in results in the same behaviour as if I had tried to step over the method call.

The actual problem I am having is with error handling. Imagine I change fooMethodCall to be the following:

public int fooMethodCall()
{
    throw new Exception();
}

and call it like so:

try 
{
    myFoo.fooMethodCall();
} 
catch Exception(e)
{
    //do something with the exception
}

If I examine e.StackTrace, it is most unhelpful:

at DynamicModule.ns.Wrapped_IFoo_dd88617b4f734f1987dc0099d195ca52.fooMethodCall()
at ConsoleApplication1.Program.Main(String[] args) 
in C:\Projects\ConsoleApplication1\Program.cs:line 152

All this tells me is that fooMethodCall failed. It could have failed right at the start, or in a method nested 5 levels down.

Several questions about this then. Does this code look right? If so, are the annoyances/problem I have listed something that is unavoidable when intercepting method calls? Is there a better way to do what I'm trying to achieve?

John
  • 1,502
  • 2
  • 13
  • 40

2 Answers2

2

I asked the same question here: Full stack trace for intercepted methods at call site in Unity, and was provided with this thread: In C#, how can I rethrow InnerException without losing stack trace?

We ended up adding another interceptor that ends up being the first in the pipeline that preserves the trace using the technique in the 2nd link. It's a bit voodoo and bad practice overall, I admit, but it was less a concern for us over getting full stack traces.

Community
  • 1
  • 1
Nick
  • 513
  • 3
  • 9
  • 1
    Could you elaborate and provide any more details on how you solved this? I'm struggling with this issue right now and can't seem to get it working. – Bela Nov 21 '13 at 21:56
2

Just set the exception of the return value to a new exception. For example:

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
    IMethodReturn r = getNext()(input, getNext);
    if (r.Exception != null) r.Exception = new Exception("NameOfInterceptor", r.Exception);
    return r;
}
Steven Pena
  • 1,184
  • 8
  • 18