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?