Reputation: 30295
I have an IRepository<>
and some Setting
entity. I know that for this entity I will need a cached repository so I want to create a ICachedRepository<Setting>
decorator and register it with Simple Injector.
The problem is that I have additional configuration that I need to pass somehow to the cached repository, e.g. expiration time span, prefetch policy, etc.
CachedRepository(IRepository repository, CachedRepositoryConfiguration configuration)
{
...
}
How can I do that? (These configuration can of course be different for different repositories, e.g. 30 minutes for one, 1 hour for another)
Upvotes: 1
Views: 141
Reputation: 172816
Simple Injector does not easily allow you to configure the constructor values of your decorators (although this can be done by implementing a custom IDependencyInjectionBehavior
- or IConstructorInjectionBehavior
in v2).
The easiest way around this is to fallback to property injection and register an initializer per decorator:
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));
});
Another option is to use Context Based injection. With the extension method given in the documentation you can do the following:
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;
}
});
A third option is to make the configuration object generic as follows:
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) { }
}
This third option allows you to remove the conditional registration altogether.
Upvotes: 1