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 + "rn");
        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:codeServiceDemoConsoleDemoProgram.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:codeServiceDemoConsoleDemoProgram.cs:line 63

拦截器中的堆栈跟踪很好,足以在服务级别进行日志记录。然而,我们失去了在呼叫站点上经过拦截代理呼叫的一切;

我可以将拦截器中的异常封装在ServiceException或类似的文件中,这将使调用堆栈保持在内部异常中,但这会导致尴尬的日志记录和调试检查场景(尽管没有完全丢失跟踪那么尴尬)。

我还注意到,当我们使用TransparentProxyInterceptor时,我们或多或少会得到我们想要的东西,但这比InterfaceInterception慢,这会给一些组敲响警钟。

有没有更干净的方法可以在代理上的调用站点通过Unity拦截获得完整的堆栈跟踪?

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

对于所有其他版本,您可以看到此问题:
在C#中,如何在不丢失堆栈跟踪的情况下重新抛出InnerException?

最新更新