【问题标题】:How do I handle Exception throw by Intercepter in C#如何在 C# 中处理拦截器引发的异常
【发布时间】:2022-01-05 23:52:10
【问题描述】:

我想Catch Interceptor 抛出的异常,该怎么做?

使用 autofac6.0.0,.NET 6

控制器>CommandAspect>命令

Interceptor 可以从 Command 中捕获异常,但 Controller 不能从 Interceptor 中捕获异常。

注册

builder.RegisterModule<AutofacScanningModule>();
builder.RegisterType<CommandAspect>();

AutofacScanningModule

public class AutofacScanningModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {

        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        builder
            .RegisterAssemblyTypes(assemblies)
            .Where(t => t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(ICommand))))
            .EnableClassInterceptors()
            .InterceptedBy(typeof(CommandAspect)); 
        base.Load(builder);
    }
}

CommandAspect

 public class CommandAspect : IInterceptor
{
    public CommandAspect()
    {
    }
    public async void Intercept(IInvocation invocation)
    {
        try
        {
            invocation.Proceed();
        }
        catch (Exception ex)
        {
            //Log Output
            throw;
        }
    }
}

网络控制器

try
{
    type commandType = typeof(CommandClass);
    object commandObject = _serviceProvider.GetService(commandType);
    commandType.GetMethod("SomeCommand").Invoke(commandObject);
}
catch(Exception ex)
{
   //not handled
}

命令

 public class CommandClass : ICommand
 {
     public virtual void SomeCommand()
     {
       throw new Exception();
     }
  }

异常堆栈跟踪

Unhandled exception. System.Exception: Exception of type 'System.Exception' was thrown.
   at Sample.SomeCommand.Find(Record record) SomeCommand.cs:line 42
   at Castle.Proxies.SomeCommandProxy.Find_callback(Record record)
   at Castle.Proxies.Invocations.SomeCommand_Find.InvokeMethodOnTarget()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Sample.CommandAspect.Intercept(IInvocation invocation) CommandAspect.cs:line 29
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__127_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
   at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callb
ack, TState& state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
   at System.Threading.Thread.StartCallback()

已解决

 public class CommandAspect : IInterceptor
{
    public CommandAspect()
    {
    }
    public void Intercept(IInvocation invocation)
    {
        ProcessInterceptAsync(invocation).Wait();

    }

    private async Task ProcessInterceptAsync(IInvocation invocation)
    {
        try
        {
            var proceed = invocation.CaptureProceedInfo();
            proceed.Invoke();
        }
        catch (Exception ex)
        {
            //Log Output
            throw;
        }
    }
}

【问题讨论】:

    标签: c# exception autofac


    【解决方案1】:

    您没有正确进行异步拦截。您必须从Intercept 返回void 并将ReturnValue 设置为Task 结果。 See the docs here..

    您的堆栈跟踪显示来自不同线程的异常,因此它没有被捕获。如果你正确设置了拦截器,我敢打赌它会按预期工作。

    【讨论】:

      【解决方案2】:

      您可以实现一个ErrorHandling 中间件来处理这个问题。由于中间件在控制器之外起作用,因此控制器不会看到错误。

      看看这个链接: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-6.0

      【讨论】:

      • 我试着写 app.UseDeveloperExceptionPage();但是即使在调试中,应用程序也会在异常之后终止。
      • 我在谈论使用中间件,比如这个答案,stackoverflow.com/questions/38630076/…
      • 调试你能不能在你的 Main 方法中添加一个全局 try catch,看看到底是什么失败了。
      • 它是 Web 应用程序。所以我尝试在 Program.cs 中编写 Try Catch ,但我无法捕捉它...谢谢您的帮助
      • 即使是 Web 应用程序也有一个 main 方法。无论如何,您应该能够在那里捕获异常。否则,如果使用 Visual Studio,您可以启用 break on all exception。这样您就可以及早发现它们。
      猜你喜欢
      • 2020-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      相关资源
      最近更新 更多