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);


    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();


    public class ConfigureStartup
        public void Configure(IServiceCollection services)
            services.AddSingleton<ICache, Cache>();

            CacheProviderExtensions.AddProvider(new DictionaryMemoryCacheProvider());
            CacheProviderExtensions.AddProvider<Any>(new CustomCacheProvider());


  • does it needs this implementation, is there a simpler way?
  • I'm looking to replace the provider registration to rely on the .net DI
  • \$\begingroup\$ why you didn't use the existing cache solutions such as MemoryCache or DistributedCache ? 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\$
    – iSR5
    Mar 2, 2022 at 11:37
  • \$\begingroup\$ @iSR5 is a try to abstract the actual cache provider (memory || distributed || ...). and enable a caching diversity each cached item type has different behavior. \$\endgroup\$
    – Shrembo
    Mar 11, 2022 at 16:10


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.