You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core中IAsyncInterceptor未触发调用的问题排查

Castle.Core.AsyncInterceptor拦截器未触发问题排查与修复

问题背景

在ASP.NET Core 8 Web API项目中使用Castle.Core.AsyncInterceptor时,TerminalService的方法能正常调用,但拦截器始终未触发。以下是问题代码及修复方案:

核心错误原因

  1. 拦截器类型不兼容:Castle的代理生成方法CreateInterfaceProxyWithTarget仅接受IInterceptor类型实例,而IAsyncInterceptor是独立的异步拦截接口,需通过AsyncInterceptorAdapter转换适配。
  2. 服务注册与获取不匹配:原代码注册的是IAsyncInterceptor,但代理创建时尝试获取IInterceptor实例,导致无法拿到拦截器。
  3. Logger未正确初始化:原拦截器内Logger在方法内赋值,存在空引用风险,不符合依赖注入规范。

修复步骤及代码修改

1. 修改服务注册逻辑

调整拦截器注册方式,将IAsyncInterceptor包装为IInterceptor:

builder.Services.AddSingleton(new ProxyGenerator());
// 将AsyncInterceptor转换为IInterceptor类型注册
builder.Services.AddScoped<IInterceptor>(sp => 
    new AsyncInterceptorAdapter(sp.GetRequiredService<LoggingInterceptor>()));
builder.Services.AddProxiedScoped<ITerminalService, TerminalService>();

2. 修正AddProxiedScoped方法

确保代理创建时能正确获取并转换异步拦截器:

public static void AddProxiedScoped<TInterface, TImplementation>(this IServiceCollection services)
    where TInterface : class
    where TImplementation : class, TInterface
{
    services.AddScoped<TImplementation>();
    services.AddScoped(typeof(TInterface), serviceProvider =>
    {
        var proxyGenerator = serviceProvider.GetRequiredService<ProxyGenerator>();
        var actual = serviceProvider.GetRequiredService<TImplementation>();
        // 获取异步拦截器并转换为IInterceptor
        var asyncInterceptor = serviceProvider.GetRequiredService<IAsyncInterceptor>();
        var interceptors = new IInterceptor[] { new AsyncInterceptorAdapter(asyncInterceptor) };
        return proxyGenerator.CreateInterfaceProxyWithTarget(typeof(TInterface), actual, interceptors);
    });
}

3. 完善LoggingInterceptor实现

通过构造函数注入Logger,确保日志功能正常:

public class LoggingInterceptor : IAsyncInterceptor
{
    private readonly ILogger<LoggingInterceptor> _logger;

    // 构造函数注入ILogger
    public LoggingInterceptor(ILogger<LoggingInterceptor> logger)
    {
        _logger = logger;
    }

    public void InterceptSynchronous(IInvocation invocation)
    {
        _logger.Information("执行同步方法: {MethodName}", invocation.Method.Name);
        invocation.Proceed();
        _logger.Information("同步方法完成: {MethodName}, 返回值: {ReturnValue}", invocation.Method.Name, invocation.ReturnValue);
    }

    public void InterceptAsynchronous(IInvocation invocation)
    {
        _logger.Information("执行异步方法: {MethodName}", invocation.Method.Name);
        invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
    }

    public void InterceptAsynchronous<TResult>(IInvocation invocation)
    {
        _logger.Information("执行异步方法(带返回值): {MethodName}", invocation.Method.Name);
        invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
    }

    private async Task InternalInterceptAsynchronous(IInvocation invocation)
    {
        invocation.Proceed();
        var task = (Task)invocation.ReturnValue;
        await task;
        _logger.Information("异步方法完成: {MethodName}", invocation.Method.Name);
    }

    private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
    {
        invocation.Proceed();
        var task = (Task<TResult>)invocation.ReturnValue;
        TResult result = await task;
        _logger.Information("异步方法(带返回值)完成: {MethodName}, 返回值: {Result}", invocation.Method.Name, result);
        return result;
    }  
}

验证

修改完成后,调用ITerminalService.SomeMethodAsync()时,拦截器的对应方法会被触发,日志中会输出方法执行的前后信息,确认拦截器生效。

内容的提问来源于stack exchange,提问作者Gringo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:05:24