代码之家  ›  专栏  ›  技术社区  ›  Toto

c类型安全的通用缓存

  •  1
  • Toto  · 技术社区  · 15 年前

    我正在寻找一种为任何对象提供通用本地缓存的方法。代码如下:

        private static readonly Dictionary<Type,Dictionary<string,object>> _cache 
            = new Dictionary<Type, Dictionary<string, object>>();
    
        //The generic parameter allow null values to be cached
        private static void AddToCache<T>(string key, T value)
        {
            if(!_cache.ContainsKey(typeof(T)))
                _cache.Add(typeof(T),new Dictionary<string, object>());
    
            _cache[typeof (T)][key] = value;
        }
    
        private static T GetFromCache<T>(string key)
        {
            return (T)_cache[typeof (T)][key];
        }   
    

    1-是否有方法不强制转换GetFromCache方法?

    2-是否有一种方法可以确保第二个词典中的类型安全,比如说所有对象都具有相同的类型。(这是由addTocache方法提供的,但我更喜欢在设计中使用类型控件)。例如具有以下类型的缓存

        Dictionary<Type,Dictionary<string,typeof(type)>>
    

    谢谢

    6 回复  |  直到 6 年前
        1
  •  12
  •   Daniel    15 年前

    试试这个:

    static class Helper<T>
    {
           internal static readonly Dictionary<string, T> cache = new Dictionary<string, T>();
    }
    private static void AddToCache<T>(string key, T value)
    {
       Helper<T>.cache[key] = value;
    }
    private static T GetFromCache<T>(string key)
    {
        return Helper<T>.cache[key];
    }
    
        2
  •  3
  •   Dmitry Ornatsky    15 年前

    为什么不直接将泛型参数放入类声明中:

    public class Cache<T>
    {
        private Dictionary<string, T> _cache = new Dictionary<string, T>();
        ...
    
    }
    

    如果你愿意,它可以是静态的

        3
  •  1
  •   Stefan Steinegger    15 年前

    除非原始类型没有装箱,否则您不会从中获得太多。

    private static readonly Dictionary<Type,Dictionary<string,object>> _cache 
        = new Dictionary<Type, IDictionary>();
    
    //The generic parameter allow null values to be cached
    private static void AddToCache<T>(string key, T value)
    {
        // create a dictionary of the correct type
        if(!_cache.ContainsKey(typeof(T)))
            _cache.Add(typeof(T),new Dictionary<string, T>());
    
        _cache[typeof (T)][key] = value;
    }
    
    private static T GetFromCache<T>(string key)
    {
        // casting the dictionary instead of the value
        Dictionary<string, T> typedDictionary = (Dictionary<string, T>)_cache[typeof (T)];
        return typedDictionary[key];
    }
    

    当然,它需要更多的找不到的处理。

        4
  •  1
  •   Chris Marisic    6 年前

    IMemoryCache

    自举:

    services.AddMemoryCache();
    

    用途:

    public class HomeController : Controller
    {
        private IMemoryCache _cache;
    
        public HomeController(IMemoryCache memoryCache)
        {
            _cache = memoryCache;
    
            var onlineAt = _cache.Get<DateTime?>("self:startup");
        }
    

    有关写入和引导的详细信息,请检查上面的链接。它结合了我的答案。您也可以使用 Microsoft.Extensions.Caching.Redis 或其他分布式缓存。

    这是现在的“官方”方法。


    后代的原始答案

    我得把这个扔出去,这看起来不像你应该做的事。无论您正在做什么,都可以通过使用依赖项注入/反转控制库、企业库缓存管理器之类的工具或使用分布式内存缓存程序(如Memcache或Microsoft Velocity)更好地实现。

        5
  •  0
  •   Filmund    15 年前

    如果在编译时不知道所需的类型,则无法创建强类型缓存。如果在运行时间之前您不知道所需的类型,那么您的问题的答案可能是“否”。

        6
  •  0
  •   Matthew Whited    15 年前

    可能会丢进几把锁,或者是几个克隆人…但这是应该的。

    class Program
    {
        static void Main(string[] args)
        {
            CacheObject<int>.Instance["hello"] = 5;
            CacheObject<int>.Instance["hello2"] = 6;
            CacheObject<string>.Instance["hello2"] = "hi";
            Console.WriteLine(CacheObject<string>.Instance["hello2"]); //returns hi
        }
    }
    
    public class CacheObject<V> : CacheObject<string, V> { }
    public class CacheObject<K,V>
    {
        private static CacheObject<K, V> _instance = new CacheObject<K, V>();
        public static CacheObject<K, V> Instance { get { return _instance; } }
    
        private Dictionary<K, V> _store = new Dictionary<K, V>();
        public T this[K index]
        {
            get { return _store.ContainsKey(index) ? _store[index] : default(V); }
            set
            {
                if (_store.ContainsKey(index)) _store.Remove(index);
                if (value != null) _store.Add(index, value);
            }
        }
    }