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
相关产品推荐
相关产品推荐

