You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 07:10:12