2012-08-01 25 views
5

我们正在研究使用Unity来处理截获的日志服务方法。但是,有一点需要注意的是,整个堆栈跟踪在呼叫站点不可用;它只能在拦截器调用中使用。Unity中呼叫站点截获方法的全堆栈跟踪

下面是一个例子设置:

public interface IExceptionService 
{ 
    void ThrowEx(); 
} 

public class ExceptionService : IExceptionService 
{ 
    public void ThrowEx() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class DummyInterceptor : IInterceptionBehavior 
{ 
    public IEnumerable<Type> GetRequiredInterfaces() 
    { 
     return Type.EmptyTypes; 
    } 

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 
    { 
     IMethodReturn ret = getNext()(input, getNext); 
     if (ret.Exception != null) 
      Console.WriteLine("Interceptor: " + ret.Exception.StackTrace + "\r\n"); 
     return ret; 
    } 

    public bool WillExecute 
    { 
     get { return true; } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IUnityContainer container = new UnityContainer(); 
     container.AddNewExtension<Interception>(); 

     container.RegisterType<IExceptionService, ExceptionService>(
      new Interceptor<InterfaceInterceptor>(), 
      new InterceptionBehavior<DummyInterceptor>()); 

     try 
     { 
      container.Resolve<IExceptionService>().ThrowEx(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Call Site: " + e.StackTrace); 
     } 

    } 
} 

下面是运行该程序的控制台输出:

Interceptor: 
at ConsoleDemo.ExceptionService.ThrowEx() in C:\code\ServiceDemo\ConsoleDemo\Program.cs:line 25 
at DynamicModule.ns.Wrapped_IExceptionService_248fe3264f81461f96d34670a0a7d45d.<ThrowEx_DelegateImplementation>__0(IMethodInvocation inputs, GetNextInterceptionBehaviorDelegate getNext) 

Call Site: 
at DynamicModule.ns.Wrapped_IExceptionService_248fe3264f81461f96d34670a0a7d45d.ThrowEx() 
at ConsoleDemo.Program.Main(String[] args) in C:\code\ServiceDemo\ConsoleDemo\Program.cs:line 63 

在拦截器堆栈跟踪是罚款,将满足服务级别的日志记录。然而,我们在呼叫站点的拦截代理呼叫之后失去了一切;

我可以将异常封装在一个ServiceException或其他类似的拦截器中,并且会将调用堆栈保留在内部异常中,但这会导致难以记录和调试检查场景(尽管比完全丢失跟踪更加笨拙)。

我也注意到当我们使用TransparentProxyInterceptor时,我们会得到或多或少的东西,但是这被称为比InterfaceInterception慢,并且触发了某些组的警报响铃。

是否有任何更清晰的方式来获得一个完整的堆栈跟踪与代理呼叫站点的统一监听?

回答

2

在.NET 4.5中会有ExceptionDispatchInfo用于此目的。

对于所有其他版本,你可以看到这样一个问题:
In C#, how can I rethrow InnerException without losing stack trace?

+0

谢谢,这个问题的答案对于我们的目的的伟大工程! – Nick 2012-08-02 20:51:21

+1

@尼克 - 你能说更多你最终做了什么吗? – 2014-03-21 16:24:38

+0

我再也无法访问该代码,但它将原始问题中的'ret.Exception'传递给接受的答案中的SO链接的示例方法(从此处实际上'PreserveStackTrace(ret.Exception)'' ](http://stackoverflow.com/a/2085377))。 我也在尝试基于反射的方法后来在评论字符串,这是工作在.NET 4.0。如果我还在研究.NET 4.5时,我会考虑使用ExceptionDispatchInfo。 – Nick 2014-03-22 18:59:22