使用Autofac为基接口的所有派生实现配置通用装饰器
问题与解决方案
问题背景
现有类层级结构如下:基接口IBase、抽象基实现BaseImplementation,以及继承自IBase的扩展接口IExtended1、IExtended2及其具体实现类:
public interface IBase { void Execute(); } public abstract class BaseImplementation : IBase { public virtual void Execute() { Console.WriteLine("BaseImplementation: Executing base functionality."); } } public interface IExtended1 : IBase { void ExtendedFunctionality1(); } public class ExtendedImplementation1 : BaseImplementation, IExtended1 { public void ExtendedFunctionality1() { Console.WriteLine("ExtendedImplementation1: Executing extended functionality 1."); } public override void Execute() { base.Execute(); Console.WriteLine("ExtendedImplementation1: Overridden base execution."); } } public interface IExtended2 : IBase { void ExtendedFunctionality2(); } public class ExtendedImplementation2 : BaseImplementation, IExtended2 { public void ExtendedFunctionality2() { Console.WriteLine("ExtendedImplementation2: Executing extended functionality 2."); } public override void Execute() { base.Execute(); Console.WriteLine("ExtendedImplementation2: Overridden base execution."); } }
希望通过BaseDecorator添加横切逻辑,作用于IBase及其所有实现类:
public class BaseDecorator : IBase { private readonly IBase _inner; public BaseDecorator(IBase inner) { _inner = inner; } public void Execute() { Console.WriteLine("BaseDecorator: Before execution."); _inner.Execute(); Console.WriteLine("BaseDecorator: After execution."); } }
要求:依赖扩展接口(如IExtended1)的消费者,注入时能获取到被BaseDecorator装饰的具体实现,且无需为新增的每个IExtendedX接口单独创建装饰器。
结论与解决方案
当前的BaseDecorator设计存在类型兼容问题:它仅实现了IBase,无法直接赋值给IExtended1/IExtended2类型(因为装饰器没有实现扩展接口的方法)。但通过Autofac结合动态代理可以完美解决这个需求,无需为每个扩展接口编写单独的装饰器。
具体实现步骤
1. 安装依赖包
首先安装Autofac的动态代理扩展包:
Install-Package Autofac.Extras.DynamicProxy
2. 实现通用拦截器
将原BaseDecorator的横切逻辑改为拦截器实现,自动适配所有继承自IBase的扩展接口:
using Castle.DynamicProxy; public class BaseExecutionInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { // 仅对IBase的Execute方法添加横切逻辑 if (invocation.Method == typeof(IBase).GetMethod(nameof(IBase.Execute))) { Console.WriteLine("BaseDecorator: Before execution."); // 执行原方法 invocation.Proceed(); Console.WriteLine("BaseDecorator: After execution."); } else { // 扩展接口的其他方法直接执行 invocation.Proceed(); } } }
3. Autofac注册配置
通过注册启用接口拦截,将拦截器应用到所有IBase的实现类上:
var builder = new ContainerBuilder(); // 注册拦截器 builder.RegisterType<BaseExecutionInterceptor>(); // 注册具体实现类,关联到对应的扩展接口,并启用拦截 builder.RegisterType<ExtendedImplementation1>() .As<IExtended1>() .EnableInterfaceInterceptors() .InterceptedBy(typeof(BaseExecutionInterceptor)); builder.RegisterType<ExtendedImplementation2>() .As<IExtended2>() .EnableInterfaceInterceptors() .InterceptedBy(typeof(BaseExecutionInterceptor)); // 构建容器 var container = builder.Build();
4. 测试验证
当消费者依赖IExtended1时,解析得到的实例会自动被拦截器装饰,执行Execute方法时会触发横切逻辑,同时不影响扩展方法的调用:
var service = container.Resolve<IExtended1>(); service.Execute(); // 输出: // BaseDecorator: Before execution. // BaseImplementation: Executing base functionality. // ExtendedImplementation1: Overridden base execution. // BaseDecorator: After execution. service.ExtendedFunctionality1(); // 输出: // ExtendedImplementation1: Executing extended functionality 1.
补充说明
如果不想使用动态代理,也可以通过泛型装饰器实现,但需要为每个扩展接口单独注册泛型装饰器,这不符合“无需为新增扩展接口单独操作”的要求,因此动态代理方案是更优选择。
内容的提问来源于stack exchange,提问作者Mike Cov
相关产品推荐
相关产品推荐

