我正在尝试集中管理某个方法的异常处理,但我似乎无法到达那里。
public class ExceptionInterceptor : IInterceptor
{
private readonly Logger _logger;
public ExceptionInterceptor(Logger logger)
{
_logger = logger;
Measure.Configure(new StatsdConfig());
}
public void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
//if ((Task<System.Threading.Tasks.VoidTaskReturn>) invocation.ReturnValue.Status == "Failed")
//{
// throw new Exception(invocation.ReturnValue.Exception[0]);
//}
}
catch (Exception e)
{
var errorMessage =
String.Format(
"An error occurred while retrieving fund data. Error Message: {0} Inner Exception: {1}",
e.Message, e.InnerException != null ? e.InnerException.Message : "<None>");
_logger.Log(errorMessage);
Measure.Counter("Exception", 1);
Measure.Event("Exception", errorMessage);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
我将它连接到一个模块中,如下所示:
builder.RegisterType<DataConsumer>().
As<IConsumer<DataRequest>>().
EnableInterfaceInterceptors().
InterceptedBy(typeof(ExceptionInterceptor));
builder.RegisterType<ExceptionInterceptor>().AsSelf();
var loggingInterceptor = new LoggingInterceptor(Logger);
builder.Register(c => loggingInterceptor);
Run Code Online (Sandbox Code Playgroud)
但是,当我在方法调用中抛出异常时,这不会作为抛出的异常冒泡到拦截器,因此它永远不会进入 catch 块。有没有办法在拦截器中捕获被拦截方法的异常?
由于某种原因,我也无法访问 invocation.ReturnValue.Status,因此无法测试是否存在抛出异常以重新抛出。
任何人都可以对我在这里可能或不会做的事情有所了解吗?
塔
由于一些不完整的信息,我很难重现您的问题。例如,您注意到IConsumer<T>接口是 MassTransit 接口,但 MassTransit 中的接口不是通用的。它还特别提到接口应该是仅用于 IoC 容器的标记,这可能会对您的接线产生一些影响。
首先,让我们发布一个有效的异常处理示例。为了自包含,我将创建一个IWorker<T>接口来代替IConsumer<T>一个简单的实现:
public interface IWorker<T>
{
bool DoWork(T message);
}
public class StringWorker : IWorker<string>
{
public bool DoWork(string message)
{
throw new DivideByZeroException();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我将创建一个简单的异常记录器,它只是将信息通过管道传输到控制台。
public class ExceptionLogger : IInterceptor
{
private readonly TextWriter _output;
public ExceptionLogger(TextWriter output)
{
_output = output;
}
public void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
}
catch(Exception ex)
{
_output.WriteLine("Logged Exception: {0}", ex.Message);
throw;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我可以将它连接起来并查看它的运行情况,如下所示:
var builder = new ContainerBuilder();
builder.RegisterInstance(Console.Out).As<TextWriter>();
builder.RegisterType<ExceptionLogger>();
builder.RegisterType<StringWorker>()
.As<IWorker<string>>()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(ExceptionLogger));
var container = builder.Build();
var worker = container.Resolve<IWorker<string>>();
worker.DoWork("Test!");
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我在程序终止之前在控制台上看到(带有未处理的异常 - 请注意我的处理程序没有吞下它,只是记录了它):
Logged Exception: Attempted to divide by zero.
Run Code Online (Sandbox Code Playgroud)
所以它的工作。
我认为您的环境中还有更多可能会在这里造成麻烦。它可能是您认为无关但实际上很重要的事情。
要调查的一般事项:
DataConsumer以立即在接口方法之一内抛出异常。构建容器后,解决一个,IConsumer<DataRequest>并调用该接口方法。它会被记录吗?IConsumer<DataRequest>还是其他什么?它包装了接口方法,而不是对象类型,因此并未涵盖所有方法。基本上,将工件减少到尽可能小的一组,直到您可以看到它在工作,然后慢慢扩展,直到找到它分解的地方。我不知道这些是否适用于您的情况,但如果我正在排除故障,这些是我会开始考虑的事情。
但是......使用拦截器以 AOP 方式处理异常确实有效,所以是其他原因造成了挑战。
| 归档时间: |
|
| 查看次数: |
1777 次 |
| 最近记录: |