[英]AOP with Autofac and DynamicProxy2 Exception Handling
I'm trying to centrally manage Exception handling for a certain method but I can't seem to get there. 我正在尝试集中管理某种方法的异常处理,但似乎无法到达那里。
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;
}
}
I'm wiring this up in a module like so: 我将其连接到如下模块中:
builder.RegisterType<DataConsumer>().
As<IConsumer<DataRequest>>().
EnableInterfaceInterceptors().
InterceptedBy(typeof(ExceptionInterceptor));
builder.RegisterType<ExceptionInterceptor>().AsSelf();
var loggingInterceptor = new LoggingInterceptor(Logger);
builder.Register(c => loggingInterceptor);
However when I throw an exception in the method invocation this doesn't bubble up to the interceptor as an exception thrown, so it never enters the catch block. 但是,当我在方法调用中引发异常时,它不会像引发的异常那样突然出现在拦截器中,因此它永远不会进入catch块。 Is there any way to catch the intercepted method's exception in the interceptor?
有什么方法可以在拦截器中捕获被拦截方法的异常吗?
I also can't access the invocation.ReturnValue.Status for some reason and as such can't test whether there was a thrown exception in order to re-throw. 由于某种原因,我也无法访问invocation.ReturnValue.Status,因此无法测试是否存在抛出异常以重新抛出。
Can anyone shed some light into what I might nor be doing right here? 谁能在这里阐明我可能也不会做的事情?
Ta 钽
I'm having a difficult time reproducing your issue due to a bit of incomplete information. 由于信息不全,我很难重现您的问题。 For example, you noted that the
IConsumer<T>
interface is a MassTransit interface, but the interface in MassTransit isn't generic . 例如,您注意到
IConsumer<T>
接口是MassTransit接口,但是MassTransit中的接口不是通用的 。 It also specifically mentions that the interface is supposed to be a marker just for IoC containers, which may have some implications on your wire-up. 它还特别提到了该接口应该是仅用于IoC容器的标记,这可能会对您的连线产生影响。
First, let's post a working exception handling example. 首先,让我们发布一个有效的异常处理示例。 To be self-contained, I'll create an
IWorker<T>
interface in place of IConsumer<T>
and a simple implementation: 为了自成体系,我将创建一个
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();
}
}
Now I'll create a simple exception logger that just pipes info to the console. 现在,我将创建一个简单的异常记录器,该记录器仅将信息传递到控制台。
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;
}
}
}
I can then wire it up and see it in action like this: 然后,我可以将其连接起来,并按如下所示进行操作:
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!");
When I run this, I see on the console just before the program dies (with the unhandled exception - note my handler didn't swallow it, just logged it): 运行此命令时,我在控制台上看到程序即将终止的状态(有未处理的异常-请注意,我的处理程序没有吞下它,只是记录了它):
Logged Exception: Attempted to divide by zero.
So it's working. 这样就可以了。
I think there's more in your environment that may be causing trouble here. 我认为您的环境中可能还有其他可能造成麻烦的地方。 It could be something you think is unrelated but is actually important.
您可能认为这无关紧要,但实际上很重要。
General things to investigate: 要调查的一般事项:
DataConsumer
to throw an exception immediately inside one of the interface methods. DataConsumer
以立即在接口方法之一内部引发异常。 After building your container, resolve a, IConsumer<DataRequest>
and call that interface method. IConsumer<DataRequest>
并调用该接口方法。 Does it get logged? IConsumer<DataRequest>
or something else? IConsumer<DataRequest>
或其他工具? It's wrapping the interface methods, not the object type, so not all methods are covered. Basically, reduce the working pieces to the smallest set possible until you can see it working, then slowly expand until you find the place it breaks down. 基本上,将工件减小到最小设置,直到您看到它可以工作为止,然后慢慢扩展直到找到它破裂的地方。 I don't know if any of these apply to your situation, but these are the things I'd start looking at if I was troubleshooting.
我不知道这些方法是否适用于您的情况,但是如果我要进行故障排除,那么我将着眼于这些。
But... exception handling in an AOP fashion using interceptors does work , so it's something else going on that's causing the challenge. 但是... 使用拦截器以AOP方式进行异常处理确实可以工作 ,因此这是造成挑战的原因。
It seems that it isn't possible for the exception thrown in the target proxy to be pushed up to the interceptor, and as such what I was trying to do didn't work. 似乎不可能将目标代理中引发的异常推送到拦截器,因此我尝试执行的操作不起作用。 I ended up handling the exceptions at the class they occur.
我最终在发生异常的类中处理异常。
Disappointed I didn't manage to get this to work the way I was intending to. 失望的是,我没能按照我想要的方式使它工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.