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

Autofac能否拦截构造函数?是否存在可行的解决方案?

Autofac中实现构造函数拦截的可行方案?

我尝试对某个类进行调用拦截,其中virtual方法的拦截可正常工作。但我还希望能拦截constructor的调用,不过我认为至少没有直接可行的方式,因为Autofac官方文档中明确说明:

使用虚方法
类拦截要求被拦截的方法必须是虚方法,因为它采用子类化作为代理技术。

快速示例

拦截器

public class TestInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        if (invocation.Method.Name == ".ctor")
            Console.WriteLine("Intercepted ctor");

        invocation.Proceed();
    }
}

被拦截类

public class ClassToBeIntercepted
{
    public ClassToBeIntercepted()
    {
        Console.WriteLine("ClassToBeIntercepted ctor");
    }

    public virtual void DoSomething()
    {
        Console.WriteLine("Doing something");
    }
}

测试示例

[TestClass]
public class TestInterception
{
    public TestContext TestContext { get; set; }

    // Create your builder.
    private static readonly ContainerBuilder builder = new();
    static Hierarchy _hierarchy = (Hierarchy)LogManager.GetRepository();
    private static IContainer container;
    protected static ILifetimeScope scope;

    [TestMethod]
    public void TestConstructorInterception()
    {
        builder.RegisterType<TestInterceptor>();
        builder.RegisterType<ClassToBeIntercepted>()
         .AsSelf()
         .EnableClassInterceptors()
         .InterceptedBy(typeof(TestInterceptor));

        using (var scope1 = builder.Build().BeginLifetimeScope())
        {
            scope1.Resolve<ClassToBeIntercepted>().DoSomething();
        }
    }
}

可行的解决办法

Autofac的类拦截基于子类化技术,而构造函数无法被声明为虚方法,因此确实无法直接通过类拦截器拦截构造函数的调用过程。但可以通过以下几种方式实现类似需求:

1. 利用Autofac生命周期钩子(最简便)

Autofac提供了OnActivating和OnActivated注册事件,能在实例构造完成后、返回给调用者之前执行自定义逻辑,覆盖大部分构造后拦截的场景:

builder.RegisterType<ClassToBeIntercepted>()
       .AsSelf()
       .EnableClassInterceptors()
       .InterceptedBy(typeof(TestInterceptor))
       .OnActivating(e => 
       {
           // 构造完成后立即执行的拦截逻辑
           Console.WriteLine("构造函数执行完成,触发拦截逻辑");
       });

2. 手动编写代理子类

自己实现继承自目标类的代理类,在代理类的构造函数中插入拦截逻辑(注意C#子类构造默认先调用基类构造,因此逻辑会在基类构造后执行):

public class ClassToBeInterceptedProxy : ClassToBeIntercepted
{
    public ClassToBeInterceptedProxy()
    {
        // 基类构造完成后执行的拦截逻辑
        Console.WriteLine("拦截构造:基类构造已完成");
    }

    // 重写虚方法以保留原拦截逻辑
    public override void DoSomething()
    {
        base.DoSomething();
    }
}

// 注册时替换为代理类
builder.RegisterType<ClassToBeInterceptedProxy>()
       .As<ClassToBeIntercepted>()
       .EnableClassInterceptors()
       .InterceptedBy(typeof(TestInterceptor));

如果需要在基类构造前执行逻辑,可以结合工厂方法:

public static class ClassFactory
{
    public static ClassToBeIntercepted CreateInstance()
    {
        Console.WriteLine("构造前拦截逻辑");
        return new ClassToBeIntercepted();
    }
}

// 注册时使用工厂方法
builder.Register(c => ClassFactory.CreateInstance())
       .As<ClassToBeIntercepted>()
       .EnableClassInterceptors()
       .InterceptedBy(typeof(TestInterceptor));

3. 改用接口拦截+工厂模式

如果目标类可以定义接口,改用接口拦截后,通过工厂类封装实例创建过程,在工厂中插入构造前后的逻辑,同时保留接口方法的拦截能力。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:27:02