Unity中调用站点截获方法的完整堆栈跟踪

时间:2012-08-01 18:03:03

标签: .net unity-container unity-interception

我们正在考虑使用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慢,并且会触发某些组的警钟。

在代理的呼叫站点上是否有更简洁的方法来获取Unity拦截的完整堆栈跟踪?

1 个答案:

答案 0 :(得分:2)

在.NET 4.5中,为此目的会有ExceptionDispatchInfo

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