unitycontainer / interception

Unity.Interception package
Apache License 2.0
22 stars 17 forks source link

exception.StackTrace is truncated when using Interceptors #3

Closed ENikS closed 6 years ago

ENikS commented 6 years ago

@cshung wrote:

Consider the following code snippet

using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; using System; using System.Collections.Generic;

namespace ConsoleApplication1 { public interface IService { void work(); }

   public class Service : IService
   {
       public void work() { a(); }
       private void a() { b(); }
       private void b() { c(); }
       private void c() { throw new NotImplementedException { }; ; }
   }

   public class Interceptor : IInterceptionBehavior
   {
       public bool WillExecute { get { return true; } }
       public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; }

       public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
       {
           Console.WriteLine("Enter invoke");
           var result = getNext()(input, getNext);
           Console.WriteLine("Exit invoke");
           return result;
       }
   }

   public class UnityStackTraceMain
   {
       static void Main(string[] args)
       {
           var container = new UnityContainer { };
           container.AddNewExtension<Interception>();
           //container.AddNewExtension<AppContainerExtension>();

           container.RegisterType<IService, Service>(
               new ContainerControlledLifetimeManager(),
               new Interceptor<InterfaceInterceptor>(),
               new InterceptionBehavior<Interceptor>());

           try
           {
               container.Resolve<IService>().work();
           }
           catch (System.Exception ex)
           {
               Console.WriteLine(ex.ToString());
               Console.WriteLine(ex.InnerException);
           }

           Console.ReadLine();
       }
   }

}

We expect the ex.ToString() has the frames a(), b() and c(), but instead, it only have the dynamic generated function.

The root cause of this is because the exception is caught and thrown again. .NET does not preserve the stack trace in the exception in that case and is clearly documented.

The proper way to fix this is to wrap the exception. In order to make existing code work with the fix. I wrap the exception with the same type and same message, that should allow most code to work with it.

Since the interceptor code is not available in this repo, I created the pull request to fix this in CodePlex instead.

https://unity.codeplex.com/SourceControl/network/forks/cshung/unity/contribution/8726

ENikS commented 6 years ago

This issue has been fixed in unitycontainer/unity/63a2f1645749f81c942ad66ecfc7949996d5a949 and should be merged from experimental branch.