简体   繁体   中英

Full stack trace missing when using Unity as AOP framework

I noticed that when using Unity as AoP framework, particularly VirtualMethodInterceptor + CallHandler.

The stack trace I got does not include the original code. Instead it has a xxx_wrapper_yyyy type of class, which I assume is a class that dynamically inherit from the original class. Understandably since no source code was ever written for the dynamic class, it is not reporting the line number where the error occurred in the original code.

How can I change this? I need the stack trace and line number where the exception was thrown.

FYI the call handler is working as intended otherwise. It's just the exception is missing the line number of the original virtual method where it happened. And no the call handler does not contain any line that will swallow or handle the exception.

Using this code

[TestMethod]
public void Should_Wrap_Exception_ThrownByTarget()
{
  var container = new UnityContainer();
  container.RegisterType<Target>(
    new Interceptor<VirtualMethodInterceptor>(), 
    new InterceptionBehavior<PolicyInjectionBehavior>());
  container.AddNewExtension<Interception>();
  var config = container.Configure<Interception>();
  config.AddPolicy("1").AddCallHandler<ExceptionHandler>().AddMatchingRule<AlwaysMatches>();
  var target = container.Resolve<Target>();
  target.AlwaysThrows("foo");
}
public class AlwaysMatches : IMatchingRule
{
  public bool Matches(MethodBase member)
  {
    return true;
  }
}
public class ExceptionHandler : ICallHandler
{
  public int Order { get; set; }
  public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
  {
    IMethodReturn r = getNext()(input, getNext);
    if (r.Exception != null)
    {
      throw new InvalidOperationException("CallHandler", r.Exception);
    }
    return r;
  }
}
public class Target
{
  public virtual string AlwaysThrows(string foo)
  {
    throw new Exception("Boom!");
  }
}

I get a stacktrace that looks like this

   at UnityExceptionAspect.Target.AlwaysThrows(String foo) in C:\VisualStudio\Evaluation\UnityExceptionAspect\Target.cs:line 9
   at DynamicModule.ns.Wrapped_Target_c49f840ef38c41d7b4d5956223e95f73.<AlwaysThrows_DelegateImplementation>__0(IMethodInvocation inputs, GetNextInterceptionBehaviorDelegate getNext)

Sorry for the poor formatting...

It definitely contains the original source of the exception although it is obfuscated by the cryptical information about the generated type.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM