如何为基于IInteractor的自定义接口批量注册Autofac泛型装饰器?
给自定义交互器接口批量注册Autofac泛型装饰器的方案
核心逻辑
你的自定义接口(比如IGetFoobar)都继承自具体的IInteractor<TRequest, TResponse>闭包泛型,所以只要通过Autofac的约定扫描找到所有这类自定义接口,就能统一为它们绑定InteractorLoggingDecorator<,>装饰器。
具体实现
1. 保留原有的交互器批量注册
确保交互器类同时注册到自身实现的自定义接口和基础IInteractor<,>接口:
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .Where(t => t.Name.EndsWith("Interactor")) .AsImplementedInterfaces() .InstancePerLifetimeScope();
2. 批量为自定义接口注册装饰器
有两种写法可选:
写法一:遍历筛选自定义接口
手动扫描程序集里所有符合条件的自定义接口,逐个注册装饰器:
var baseInteractorType = typeof(IInteractor<,>); // 找出所有继承自IInteractor<,>闭包泛型的自定义接口 var customInterfaces = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => t.IsInterface && !t.IsGenericTypeDefinition && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == baseInteractorType)); foreach (var customInterface in customInterfaces) { // 获取该自定义接口对应的IInteractor泛型参数 var matchedInteractor = customInterface.GetInterfaces() .First(i => i.GetGenericTypeDefinition() == baseInteractorType); var requestType = matchedInteractor.GetGenericArguments()[0]; var responseType = matchedInteractor.GetGenericArguments()[1]; // 构造对应的装饰器类型 var decoratorType = typeof(InteractorLoggingDecorator<,>).MakeGenericType(requestType, responseType); // 为自定义接口注册装饰器 builder.RegisterDecorator(decoratorType, customInterface); }
写法二:用Autofac的装饰器条件匹配
通过RegisterDecorator的重载,直接筛选符合条件的服务类型,自动应用装饰器:
builder.RegisterDecorator( (ctx, decoratedInstance) => { // 从被装饰实例中拿到对应的IInteractor泛型信息 var interactorInterface = decoratedInstance.GetType() .GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IInteractor<,>)); var genericArgs = interactorInterface.GetGenericArguments(); // 构造装饰器实例 return Activator.CreateInstance( typeof(InteractorLoggingDecorator<,>).MakeGenericType(genericArgs), decoratedInstance ); }, // 筛选条件:是接口、不是IInteractor<,>本身、且继承自IInteractor<,> serviceType => serviceType.IsInterface && serviceType != typeof(IInteractor<,>) && serviceType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IInteractor<,>)) );
注意事项
- 自定义接口必须继承具体的闭包泛型
IInteractor<TReq, TRes>,不能直接继承泛型定义IInteractor<,> - 装饰器的注册代码一定要放在交互器注册代码之后,不然Autofac找不到要装饰的服务
内容的提问来源于stack exchange,提问作者user13842370
相关产品推荐
相关产品推荐

