Reputation: 510
I recently decided to implement caching using the interceptor functionality from castle. It works fine.
My question: If I wanted to avoid the interceptor for a particular call, what strategy would you suggest using?
I've already determined I could have two implementations of a given service one that supports the caching aspect and one that doesn't. I could then call the appropriate one from wherever. I don't like that for many reasons.
I'd be ok with invalidating the cache at the point I knew it would be invalid, but I couldn't come up with a good solution following this line of thinking that still kept caching concerns out of my code.
Upvotes: 1
Views: 1620
Reputation: 556
I have used caching with the help of castle windsors interceptors and I have had the same problem. Generally a service should not know if a dependency is cache enabled or not. This would be a violation of the single responsibility principle.
If you are NOT ok with this code smell you could:
Register your components as named components with and without caching. Then you could selectively use those named components.
var container = new WindsorContainer();
container.Register(Component.For<CachingInterceptor>()
.Instance(new CachingInterceptor(new Cache(TimeoutStyle.RenewTimoutOnQuery, TimeSpan.FromSeconds(3)))));
container.Register(Component.For<IRepo>().ImplementedBy<Repo>().Named("Without"));
container.Register(Component.For<IRepo>().ImplementedBy<Repo>().Interceptors<CachingInterceptor>().Named("With"));
container.Register(Component.For<Service>());
container.Register(Component.For<Game>().DependsOn(Property.ForKey<IRepo>().Is("With")));
var service = container.Resolve<Service>();
var game = container.Resolve<Game>();
Console.WriteLine("Cache is not used");
service.Invoke();
service.Invoke();
Console.WriteLine();
Console.WriteLine("Cache is used");
game.Invoke();
game.Invoke();
I have this project on github: https://github.com/kobbikobb/Caching
If you are ok with this code smell you could:
1. I have used different interfaces depending on when I want to use caching or not. IService vs IServiceWithCache.
2. Implement a singleton thead safe "caching enabled" service to enable/disable caching. If you want to mock this service you could by implementing it with ambient context.
CacheSettings.Disable();
try
{
...
}
finally
{
CacheSettings.Enable();
}
Upvotes: 0
Reputation: 3070
I usually use decorators for caching concerns.
About removing / invalidating cache item I came out with a solution event based:
real service exposes events for those behaviors changing the system(for ex adding or update an item), decorator service(caching strategy) registers itseself to those events to manage the cache.
Upvotes: 2