我正在尝试集中管理某种方法的异常处理,但我似乎无法到达那里。
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;
}
}
我在这样的模块中接线:
builder.RegisterType<DataConsumer>().
As<IConsumer<DataRequest>>().
EnableInterfaceInterceptors().
InterceptedBy(typeof(ExceptionInterceptor));
builder.RegisterType<ExceptionInterceptor>().AsSelf();
var loggingInterceptor = new LoggingInterceptor(Logger);
builder.Register(c => loggingInterceptor);
然而,当我在方法调用中抛出一个异常时,这不会作为抛出的异常冒泡到拦截器,因此它永远不会进入catch块。 有没有办法在拦截器中捕获截获的方法的异常?
由于某些原因,我也无法访问invocation.ReturnValue.Status,因此无法测试是否存在抛出异常以便重新抛出。
任何人都可以对我可能做的事情有所了解吗?
TA
答案 0 :(得分:4)
由于信息不完整,我很难重现您的问题。例如,您注意到IConsumer<T>
接口是MassTransit接口,但是{{3 }}。它还特别提到接口应该只是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();
}
}
现在我将创建一个简单的异常记录器,只需将信息传递给控制台。
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;
}
}
}
然后我可以将它连接起来并按照以下方式查看它:
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!");
当我运行它时,我会在程序死亡之前在控制台上看到(带有未处理的异常 - 注意我的处理程序没有吞下它,只记录它):
Logged Exception: Attempted to divide by zero.
所以它正在发挥作用。
我认为你的环境中可能会有更多麻烦在这里造成麻烦。这可能是你认为不相关但实际上很重要的东西。
要调查的一般事项:
DataConsumer
以立即在其中一个接口方法中引发异常。构建容器后,解析一个IConsumer<DataRequest>
并调用该接口方法。它会被记录吗?IConsumer<DataRequest>
或其他内容?它包装了接口方法,而不是对象类型,因此不是所有方法都被覆盖。基本上,将工件减少到可能的最小值,直到看到它工作,然后慢慢展开,直到找到它发生故障的地方。我不知道这些是否适用于您的情况,但如果我进行故障排除,这些是我开始考虑的事情。
但是...... 使用拦截器以AOP方式进行异常处理确实有效,所以这是导致挑战的其他因素。
答案 1 :(得分:-1)
似乎将目标代理中抛出的异常推送到拦截器是不可能的,因此我试图做的事情并没有起作用。我最终在他们发生的课程中处理了异常。
失望我没有设法以我想要的方式工作。