简体   繁体   English

具有Autofac和DynamicProxy2异常处理的AOP

[英]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: 要调查的一般事项:

  • Temporarily update your 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? 它被记录了吗?
  • Look at the places that you're expecting to see logging occur. 查看您期望看到日志记录的地方。 Are you resolving and working with IConsumer<DataRequest> or something else? 您是否正在解决和使用IConsumer<DataRequest>或其他工具? It's wrapping the interface methods, not the object type, so not all methods are covered. 它包装了接口方法,而不是对象类型,因此并没有涵盖所有方法。
  • Set a breakpoint in the interceptor and see if any invocation at all is passing through it. 在拦截器中设置一个断点,看看是否有任何调用通过它。 It won't catch exceptions if it's not being hit. 如果没有被击中,它将不会捕获异常。 :) :)
  • Check to see if there's any other exception handling policies or code in action. 检查是否还有其他异常处理策略或代码正在运行。 For example, some folks use the Enterprise Library exception handling block to deal with exceptions and that may be interfering with your work here. 例如,某些人使用企业库异常处理块来处理异常,这可能会干扰您在此处的工作。
  • I've not used MassTransit, but check to see if there's any other object proxying going on. 我没有使用过MassTransit,但请检查是否有其他任何对象代理正在进行。 (Doubtful, but I know I've run into this with products like Glimpse, so you end up with proxies wrapped around proxies, which becomes challenging.) (令人怀疑,但我知道我已经在诸如Glimpse之类的产品中遇到过这种情况,因此您最终只能将代理服务器包裹在代理服务器中,这变得很有挑战性。)
  • Is the exception actually happening in the place you think it is? 异常确实发生在您认为是的地方吗? It may be happening and getting handled somewhere that isn't wrapped with the proxy. 它可能正在发生,并且在没有用代理包装的地方得到处理。

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.

相关问题 使用autofac和dynamicproxy2的选择性拦截方法 - Selectively intercepting methods using autofac and dynamicproxy2 DynamicProxy2:CreateClassProxyWithTarget + IInterceptor - DynamicProxy2: CreateClassProxyWithTarget + IInterceptor Autofac.Extras.DynamicProxy2 v3.0.6出现异常 - Autofac.Extras.DynamicProxy2 v3.0.6 got a exception 帮助将mixins从Castle.DynamicProxy迁移到DynamicProxy2 - Help Migrating mixins from Castle.DynamicProxy to DynamicProxy2 具有类型参数的Autofac DynamicProxy - Autofac DynamicProxy with type parameters 异常处理:AOP与经典处理? - Exception Handling : AOP vs Classic Handling? Autofac全局接口拦截器与Autofac.Extras.DynamicProxy2 - Autofac global interface interceptor with Autofac.Extras.DynamicProxy2 带有Ninject拦截的AOP,Castle DynamicProxy和WPF窗口:在窗口的DynamicProxy中找不到XAML资源 - AOP with Ninject Interception, Castle DynamicProxy and WPF window: Can't find XAML resource in DynamicProxy of window 是否可以使用面向方面的方法通过 Autofac 和 DynamicProxy 登录 Azure 函数 - Is it possible to use an aspect oriented approach to logging in an Azure function with Autofac and DynamicProxy Autofac.Extras.DynamicProxy 在公共接口上出错 - Autofac.Extras.DynamicProxy got error with public interface
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM