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 . 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?