C # универсальный кеш с типом safe - PullRequest
1 голос
/ 07 августа 2009

Я ищу способ иметь общий локальный кеш для любого объекта. Вот код:

    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, но я бы предпочел контроль типов в самом дизайне). Например, чтобы иметь _cache следующего типа

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

Thx

Ответы [ 6 ]

12 голосов
/ 07 августа 2009

Попробуйте это:

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];
}
3 голосов
/ 07 августа 2009

Почему бы просто не добавить универсальный параметр в объявление класса:

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

}

может быть статичным, если вы предпочитаете

1 голос
/ 07 августа 2009

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 или другие распределенные кэши.

Теперь это «официальный» подход.


Оригинальный ответ для потомков

Я должен выбросить это, это не похоже на то, что вы должны делать. То, что вы делаете, скорее всего, может быть гораздо лучше достигнуто либо с помощью внедрения зависимостей / инверсии библиотеки управления, такого инструмента, как Enterprise Library CacheManager, либо с помощью программы кэширования распределенной памяти, такой как Memcache или Microsoft Velocity.

1 голос
/ 07 августа 2009

Вы не получите много с этим, если только эти примитивные типы не упакованы.

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];
}

Конечно, нужно больше не найденных обработок.

0 голосов
/ 07 августа 2009

, вероятно, следует добавить несколько замков и, возможно, несколько клонов ... но это должно сработать.

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);
        }
    }
}
0 голосов
/ 07 августа 2009

Вы не сможете создать кеш со строгой типизацией, если вы не знаете требуемый тип во время компиляции. Если вы не знаете требуемый тип до времени выполнения, то я боюсь, что ответы на ваши вопросы - нет и нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...