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

Autofac DynamicProxy缓存拦截器同类内部方法调用不生效问题求助

问题根源

你当前使用的是接口拦截模式:Autofac DynamicProxy 会生成实现了IClassRepository接口的代理类,代理类内部持有真实ClassRepository实例,外部调用接口方法时会先走代理的拦截逻辑,因此调用Method2时拦截生效。但同一个类内部Method2调用Method1是真实实例直接调用自身方法,没有走代理层,因此拦截器不会触发。


解决方案

方案1:改用类代理(虚方法拦截,改动最小)

这种方式会让代理类继承自你的Repository实现类,重写带拦截逻辑的虚方法,内部调用也会走代理重写后的逻辑。

  1. 将Repository内需要被拦截的方法改为virtual修饰:
public class ClassRepository : IClassRepository
{
    [Cache]
    // 加virtual修饰
    public virtual async Task<List<string>> Method1()
    {
       //Do some thing
    }

    [Cache]
    // 加virtual修饰
    public virtual async Task<List<string>> Method2()
    {
       var methodCall = await Method1();
    }
}
  1. 修改Autofac注册代码,将EnableInterfaceInterceptors改为EnableClassInterceptors:
public class RepositoryModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<CacheInterceptor>();
        var flightDataAccess = Assembly.Load("DataAccess");
        builder.RegisterAssemblyTypes(flightDataAccess)
            .Where(x => x.Name.EndsWith("Repository"))
            .AsImplementedInterfaces()
            .InstancePerLifetimeScope()
            .InterceptedBy(typeof(CacheInterceptor))
            // 替换原来的EnableInterfaceInterceptors
            .EnableClassInterceptors();
    }
}

方案2:内部注入自身接口实例,不直接用this调用

如果不想改方法为虚方法,可以在类内部注入代理后的接口实例,内部调用时用注入的实例调用:

public class ClassRepository : IClassRepository
{
    private readonly IClassRepository _proxySelf;

    // 注入自身的接口实例,Autofac会自动注入代理后的对象
    public ClassRepository(IClassRepository proxySelf)
    {
        _proxySelf = proxySelf;
    }

    [Cache]
    public async Task<List<string>> Method1()
    {
       //Do some thing
    }

    [Cache]
    public async Task<List<string>> Method2()
    {
       // 调用代理实例的方法,触发拦截
       var methodCall = await _proxySelf.Method1();
    }
}

注意:需要确保Repository的生命周期不是单例,避免循环依赖问题,你当前用的InstancePerLifetimeScope完全支持这种写法。


额外优化建议

你当前拦截器中ProcessInterceptAsync(invocation).Wait()是同步阻塞异步方法,高并发场景下容易出现死锁,建议改用Castle官方的AsyncInterceptor基类实现异步拦截,避免阻塞问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:06:01