我正在使用一个使用 Unity (v2.0) 作为 Microsoft Enterprise Library 一部分的应用程序。它被设置为您可以在方法的顶部添加一个属性,并且在方法执行之前会完成一些事情(跟踪/记录/缓存等)。下面的示例代码:
static void Main(string[] args)
{
IUnityContainer myContainer = new UnityContainer()
.AddNewExtension<Interception>()
.RegisterType<IFoo, Foo>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<PolicyInjectionBehavior>()
);
IFoo myFoo = myContainer.Resolve<IFoo>();
myFoo.fooMethodCall();
}
public class TraceAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new TraceCallHandler();
}
}
public class TraceCallHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn;
//Do tracing/chaching/other funky stuff
methodReturn = getNext()(input, getNext);
return methodReturn;
}
}
public interface IFoo
{
int fooMethodCall();
}
public class Foo : IFoo
{
[Trace]
public int fooMethodCall()
{
return 0;
}
}
现在,我对这种工作方式有两个烦恼,一个非常严重的问题。第一个烦恼是生成的堆栈跟踪的大小。尝试调试 5 级深度的函数会导致一些难以导航的可怕堆栈跟踪。
第二个烦恼是使用VS2010调试的时候,似乎无法进入fooMethodCall
. 尝试介入会导致与我尝试跨过方法调用相同的行为。
我遇到的实际问题是错误处理。想象一下,我更改fooMethodCall
为以下内容:
public int fooMethodCall()
{
throw new Exception();
}
并这样称呼它:
try
{
myFoo.fooMethodCall();
}
catch Exception(e)
{
//do something with the exception
}
如果我检查 e.StackTrace,它是最无用的:
at DynamicModule.ns.Wrapped_IFoo_dd88617b4f734f1987dc0099d195ca52.fooMethodCall()
at ConsoleApplication1.Program.Main(String[] args)
in C:\Projects\ConsoleApplication1\Program.cs:line 152
这一切告诉我的是 fooMethodCall 失败了。它可能在一开始就失败了,或者在嵌套 5 层的方法中失败了。
那么关于这个的几个问题。这段代码看起来对吗?如果是这样,我列出的烦恼/问题是否在拦截方法调用时是不可避免的?有没有更好的方法来做我想要实现的目标?