DryIoc:注册双接口装饰器并获取对应实例
解决方案:收集DI中装饰器实例注入到IFlushable数组
这个方案完全可行,核心思路是在注册装饰器时跟踪实例,或者从DI容器中获取已注册的装饰器实例,再将这些实例注册为IFlushable集合,确保注入到CacheHandler的是与对应服务绑定的同一个装饰器实例。以下以Simple Injector为例给出具体实现:
1. 定义基础接口与类
// 基础服务接口 public interface IService { void DoWork(); } public class Service : IService { public void DoWork() { /* 业务逻辑 */ } } // 缓存刷新接口 public interface IFlushable { void FlushCache(); } // 缓存装饰器(同时实现IService和IFlushable) public class CachingService : IService, IFlushable { private readonly IService _decorated; public CachingService(IService decorated) => _decorated = decorated; public void DoWork() { /* 带缓存的业务逻辑 */ } public void FlushCache() { /* 刷新当前服务缓存 */ } } // 另一个服务示例 public interface IOrderService { void ProcessOrder(); } public class OrderService : IOrderService { public void ProcessOrder() { /* 订单业务逻辑 */ } } public class OrderCachingDecorator : IOrderService, IFlushable { private readonly IOrderService _decorated; public OrderCachingDecorator(IOrderService decorated) => _decorated = decorated; public void ProcessOrder() { /* 带缓存的订单逻辑 */ } public void FlushCache() { /* 刷新订单缓存 */ } } // 缓存处理器,接收IFlushable数组 public class CacheHandler { private readonly IFlushable[] _cacheFlushers; public CacheHandler(IFlushable[] cacheFlushers) => _cacheFlushers = cacheFlushers; public void FlushAllCaches() { foreach (var flusher in _cacheFlushers) { flusher.FlushCache(); } } }
2. DI容器注册与实例收集
方式一:注册装饰器时直接跟踪实例
var container = new Container(); // 1. 注册原始服务(这里用单例,根据实际需求调整生命周期) container.Register<IService, Service>(Lifestyle.Singleton); container.Register<IOrderService, OrderService>(Lifestyle.Singleton); // 2. 初始化集合保存IFlushable装饰器实例 var flushableDecorators = new List<IFlushable>(); // 3. 注册装饰器,同时将实例加入集合 container.RegisterDecorator<IService, CachingService>(Lifestyle.Singleton, (context, decorated) => { var decorator = new CachingService(decorated); flushableDecorators.Add(decorator); return decorator; }); container.RegisterDecorator<IOrderService, OrderCachingDecorator>(Lifestyle.Singleton, (context, decorated) => { var decorator = new OrderCachingDecorator(decorated); flushableDecorators.Add(decorator); return decorator; }); // 4. 将集合注册为IFlushable数组实例 container.RegisterInstance<IFlushable[]>(flushableDecorators.ToArray()); // 5. 注册CacheHandler container.Register<CacheHandler>(Lifestyle.Singleton); // 验证容器配置 container.Verify();
方式二:从容器获取已注册的装饰器实例
如果不想在注册时手动跟踪,可以通过容器的注册信息直接获取装饰器实例:
var container = new Container(); // 1. 注册原始服务与装饰器 container.Register<IService, Service>(Lifestyle.Singleton); container.RegisterDecorator<IService, CachingService>(Lifestyle.Singleton); container.Register<IOrderService, OrderService>(Lifestyle.Singleton); container.RegisterDecorator<IOrderService, OrderCachingDecorator>(Lifestyle.Singleton); // 2. 获取装饰器实例(注册后,服务的Current实例就是装饰器) var cachingService = (IFlushable)container.GetRegistration(typeof(IService)).Current.GetInstance(); var orderCachingDecorator = (IFlushable)container.GetRegistration(typeof(IOrderService)).Current.GetInstance(); // 3. 注册IFlushable数组 container.RegisterInstance<IFlushable[]>(new[] { cachingService, orderCachingDecorator }); // 4. 注册CacheHandler并验证 container.Register<CacheHandler>(Lifestyle.Singleton); container.Verify();
关键注意事项
- 生命周期一致性:装饰器、IFlushable数组、CacheHandler的生命周期必须匹配(比如都用单例,或者都用作用域),避免出现实例不匹配的问题。
- 装饰器注册顺序:确保装饰器在原始服务之后注册,否则容器无法正确解析装饰器包裹的服务。
- 多作用域场景适配:如果使用作用域生命周期(比如Web请求作用域),需要在每个作用域内收集装饰器实例,可以通过容器的
ScopeCreated事件实现。
内容的提问来源于stack exchange,提问作者LittlePilgrim
相关产品推荐
相关产品推荐

