如何将额外的依赖项/配置注入装饰器 class

How to inject additional dependencies / configuration into a decorated class

我有一个 IRepository<> 和一些 Setting 实体。我知道对于这个实体,我需要一个缓存存储库,所以我想创建一个 ICachedRepository<Setting> 装饰器并使用 Simple Injector 注册它。

问题是我有额外的配置需要以某种方式传递到缓存的存储库,例如过期时间跨度、预取策略等

CachedRepository(IRepository repository, CachedRepositoryConfiguration configuration)
{
   ...
}

我该怎么做? (这些配置对于不同的存储库当然可以不同,例如一个 30 分钟,另一个 1 小时)

Simple Injector 不允许您轻松配置装饰器的构造函数值(尽管这可以通过 implementing a custom IDependencyInjectionBehavior - 或 v2 中的 IConstructorInjectionBehavior 完成)。

解决此问题的最简单方法是回退到 属性 注入并为每个装饰器注册一个初始化程序:

public class CachingRepositoryDecorator<TEntity> : IRepository<TEntity>
{
    private readonly IRepository<TEntity> decoratee;
    public CachingRepositoryDecorator(IRepository<TEntity> decoratee) {
        this.decoratee = decoratee;
        this.Configuration = CachedRepositoryConfiguration.NoCaching;
    }

    public CachedRepositoryConfiguration Configuration { get; set; }

    // IRepository<T> methods here.
}

container.RegisterDecorator(typeof(IRepository<>), 
    typeof(CachingRepositoryDecorator<>));

container.RegisterInitializer<CachingRepositoryDecorator<Setting>>(decorator => {
   decorator.Configuration = 
       CachedRepositoryConfiguration.AbsoluteExpiration(TimeSpan.FromMinutes(30));
});

另一种选择是使用 Context Based injection。使用文档中给出的扩展方法,您可以执行以下操作:

public class CachingRepositoryDecorator<TEntity> : IRepository<TEntity>
{
    private readonly IRepository<TEntity> decoratee;
    private readonly CachedRepositoryConfiguration configuration;
    public CachingRepositoryDecorator(IRepository<TEntity> decoratee,
        CachedRepositoryConfiguration configuration) {
        this.decoratee = decoratee;
        this.configuration = configuration;
    }

    // IRepository<T> methods here.
}

container.RegisterDecorator(typeof(IRepository<>), 
    typeof(CachingRepositoryDecorator<>));

container.RegisterWithContext<CachedRepositoryConfiguration>(context => {
    if (context.ImplementationType == typeof(CachingRepositoryDecorator<Setting>)) {
        return CachedRepositoryConfiguration.AbsExpiration(TimeSpan.FromMinutes(30));
    } else {
        CachedRepositoryConfiguration.NoCaching;
    }
});

第三个选项是使配置对象通用,如下所示:

public class CachingRepositoryDecorator<TEntity> : IRepository<TEntity>
{
    private readonly IRepository<TEntity> decoratee;
    private readonly CachedRepositoryConfiguration<TEntity> configuration;
    public CachingRepositoryDecorator(IRepository<TEntity> decoratee,
        CachedRepositoryConfiguration<TEntity> configuration) {
        this.decoratee = decoratee;
        this.configuration = configuration;
    }

    // IRepository<T> methods here.
}

container.RegisterDecorator(typeof(IRepository<>), 
    typeof(CachingRepositoryDecorator<>));

container.RegisterSingleton<CachedRepositoryConfiguration<Setting>>(
    CachedRepositoryConfiguration<Setting>.Absolute(TimeSpan.FromMinutes(30)));

container.RegisterSingleton<CachedRepositoryConfiguration<Customer>>(
    CachedRepositoryConfiguration<Customer>.Sliding(TimeSpan.FromMinutes(5)));

// Register the 'no caching' configuration as fallback
container.Register(
    typeof(CachedRepositoryConfiguration<>),
    typeof(NoCachingCachedRepositoryConfiguration<>).
    Lifestyle.Singleton);

public sealed class NoCachingCachedRepositoryConfiguration<T>
    : CachedRepositoryConfiguration<T>
{
    public NoCachingCachedRepositoryConfiguration() : base(cache: false) { }
}

第三个选项允许您完全删除有条件的注册。