【发布时间】:2023-12-10 13:13:02
【问题描述】:
我开始使用 ninject 拦截器来包装我的一些具有各种行为的异步代码,并且在让一切正常工作时遇到了一些麻烦。
这是我正在使用的拦截器:
public class MyInterceptor : IInterceptor
{
public async void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
//check that method indeed returns Task
await (Task) invocation.ReturnValue;
RecordSuccess();
}
catch (Exception)
{
RecordError();
invocation.ReturnValue = _defaultValue;
throw;
}
}
这似乎在大多数正常情况下都能正常运行。我不确定这是否会达到我的预期。尽管它似乎异步地将控制流返回给调用者,但我仍然有点担心代理无意中阻塞线程或其他东西的可能性。
除此之外,我无法让异常处理正常工作。对于这个测试用例:
[Test]
public void ExceptionThrown()
{
try
{
var interceptor = new MyInterceptor(DefaultValue);
var invocation = new Mock<IInvocation>();
invocation.Setup(x => x.Proceed()).Throws<InvalidOperationException>();
interceptor.Intercept(invocation.Object);
}
catch (Exception e)
{
}
}
我可以在拦截器中看到 catch 块被击中,但我的测试中的 catch 块从未被 rethrow 击中。我更困惑,因为这里没有代理或任何东西,只有非常简单的模拟和对象。我还在测试中尝试了Task.Run(() => interceptor.Intercept(invocation.Object)).Wait(); 之类的东西,但仍然没有变化。测试顺利通过,但 nUnit 输出确实有异常消息。
我想我把事情搞砸了,我并不像我想的那样完全理解发生了什么。有没有更好的方法来拦截异步方法?我在异常处理方面做错了什么?
【问题讨论】:
-
我认为这可能与
IInterceptor.Intercept方法无效有关。我可以让它异步,但也许我在测试中没有正确地等待它或其他东西。不过这对我来说没有意义,因为在这条路径中甚至还没有发生任何异步事件。 -
在深入挖掘时,在我看来,异常是在与主测试线程具有不同同步上下文的线程上引发的。由于它是一个 void 我无法真正同步等待它或捕获它的异常。除了重写拦截插件,我能做些什么吗?
-
async void方法几乎总是一个坏主意,除非您正在编写事件处理程序。我认为要做到这一点,Ninject 必须支持async。
标签: c# ninject async-await ninject-interception