如何将额外的依赖项/配置注入装饰器 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) { }
}
第三个选项允许您完全删除有条件的注册。
我有一个 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) { }
}
第三个选项允许您完全删除有条件的注册。