Autofac:如何正确装饰实现多服务的单个组件
问题:Autofac多接口组件的装饰器注册异常
我有一个实现多个接口的组件,定义如下:
public interface IService1 { } public interface IService2 { } public interface IService3 { } public interface ICommonService : IService1, IService2, IService3 { } public class CoreComponent : ICommonService { }
对应的装饰器实现:
public class DecoratorComponent : ICommonService { public DecoratorComponent(ICommonService coreComponent) { } }
我需要解析IService1、IService2、IService3和ICommonService的实例,要求:
CoreComponent必须是单例DecoratorComponent要么是单例,要么每个服务对应一个独立的装饰器实例,但所有装饰器都仅装饰同一个核心实例
但按照以下方式注册后,解析IService1时会得到多层嵌套的装饰器实例(装饰器嵌套装饰器再包裹核心组件),不符合预期:
builder .RegisterType<CoreComponent>() .As<ICommonService>() .As<IService1>() .As<IService2>() .As<IService3>() .SingleInstance(); builder.RegisterDecorator<DecoratorComponent, ICommonService>(); builder.RegisterDecorator<DecoratorComponent, IService1>(); builder.RegisterDecorator<DecoratorComponent, IService2>(); builder.RegisterDecorator<DecoratorComponent, IService3>();
解决方案
问题根源在于原始注册中,CoreComponent同时关联了多个接口,Autofac的装饰器注册会对整个服务链进行装饰,导致嵌套。我们可以通过命名服务的方式,将核心组件单独注册,再为每个接口分别绑定并添加装饰器,确保装饰器仅包裹原始核心实例:
// 1. 注册核心组件为命名单例服务,确保全局唯一实例 builder.RegisterType<CoreComponent>() .Named<ICommonService>("core-service") .SingleInstance(); // 2. 为ICommonService注册:绑定到命名核心服务,并添加装饰器 builder.Register(ctx => ctx.ResolveNamed<ICommonService>("core-service")) .As<ICommonService>() .DecorateWith<DecoratorComponent>(); // 3. 为每个子接口单独注册:同样绑定到命名核心服务,添加装饰器 builder.Register(ctx => ctx.ResolveNamed<ICommonService>("core-service")) .As<IService1>() .DecorateWith<DecoratorComponent>(); builder.Register(ctx => ctx.ResolveNamed<ICommonService>("core-service")) .As<IService2>() .DecorateWith<DecoratorComponent>(); builder.Register(ctx => ctx.ResolveNamed<ICommonService>("core-service")) .As<IService3>() .DecorateWith<DecoratorComponent>();
如果需要DecoratorComponent也作为单例,只需在注册时添加.SingleInstance()即可:
builder.Register(ctx => ctx.ResolveNamed<ICommonService>("core-service")) .As<ICommonService>() .DecorateWith<DecoratorComponent>() .SingleInstance();
这种方式下,所有接口解析得到的装饰器都会直接包裹同一个CoreComponent单例,不会出现多层嵌套的问题。
内容的提问来源于Stack Exchange,提问作者tsul
相关产品推荐
相关产品推荐

