What I'm trying to do
- abstract the caching actual cache provider (memory || distributed || ...).
- enable a caching diversity. each
cached item type
has different behavior. - simply add more than one cache provider. and decide what provider to use with each cached record type based on configuration and settings
there are several layers
- abstracted cache
- cache factory (collect and detect the providers)
- cache providers
- cache implementation (e.g.
MemoryCache
)
interface ICache
{
T Get<T>(string key);
T Set<T>(string key, T value);
}
interface ICacheProvider
{
ICache Get();
}
Cache factory and providers store
public class CacheFactory
{
public ICache GetOrCreate<T>() => CacheProviderExtensions.GetProvider<T>().Get();
}
public static class CacheProviderExtensions
{
private const string DefaultCacheProvider = "DefaultCacheProvider";
private static readonly Dictionary<string, ICacheProvider> providers = new();
public static ICacheProvider GetProvider() => providers[DefaultCacheProvider];
public static ICacheProvider GetProvider<T>() => providers[DefaultCacheProvider];
public static void AddProvider(ICacheProvider provider) => providers.Add(DefaultCacheProvider, provider);
public static void AddProvider<T>(ICacheProvider provider) => providers.Add(nameof(T), provider);
}
abstracted implementation
public class Cache : ICache
{
private readonly CacheFactory cacheFactory;
public T Get<T>(string key) => cacheFactory.GetOrCreate<T>().Get<T>(key);
public T Set<T>(string key, T value) => cacheFactory.GetOrCreate<T>().Set<T>(key, value);
}
sample
public class DictionaryMemoryCache : ICache
{
readonly Dictionary<string, object> cache = new Dictionary<string, object>();
public T Get<T>(string key) => (T)cache[key];
public T Set<T>(string key, T value)
{
cache[key] = value;
return value;
}
}
public class CustomCache : ICache
{
public T Get<T>(string key) => default; //some-logic ...
public T Set<T>(string key, T value) => default; //some-logic ...
}
public class DictionaryMemoryCacheProvider : ICacheProvider
{
public ICache Get() => new DictionaryMemoryCache();
}
public class CustomCacheProvider : ICacheProvider
{
public ICache Get() => new CustomCache();
}
registration
public class ConfigureStartup
{
public void Configure(IServiceCollection services)
{
services.AddSingleton<ICache, Cache>();
services.AddSingleton<CacheFactory>();
CacheProviderExtensions.AddProvider(new DictionaryMemoryCacheProvider());
CacheProviderExtensions.AddProvider<Any>(new CustomCacheProvider());
}
}
issues:
- does it needs this implementation, is there a simpler way?
- I'm looking to replace the provider registration to rely on the .net DI
MemoryCache
orDistributedCache
? what does your solution solve and offer over them ? Perhaps if you share a brief explanation on the dilemma that drove you to implement this, it would add more value to the question, and also would help the community for providing a better answer. \$\endgroup\$cached item type
has different behavior. \$\endgroup\$