65.9K
CodeProject 正在变化。 阅读更多。
Home

通用延迟加载缓存类

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.25/5 (4投票s)

2008 年 9 月 3 日

CPOL

2分钟阅读

viewsIcon

53443

提供了一个用于创建单例延迟加载缓存的基础类。

引言

这个通用类可以被继承,并用作延迟加载对象的简单内存缓存。

背景

在我的应用程序中,我注意到我经常实现一个延迟加载缓存。我将其用于从数据库加载的静态或近乎静态的数据,并且我不想在对象图中多次拥有这些数据。

该类的要求是:

  • 仅加载对象一次。 初始加载后,对该对象的请求将返回已在内存中的副本(即延迟加载)。
  • 缓存的单例模式,确保只有一个实例。
  • 通过键对象检索对象(字典)。
  • 派生类负责对象的初始加载。

做过几次之后,我认为我可以使用泛型来创建一个可重用的缓存基类。 我想使用模板模式,以便每个派生类实现自己的加载机制,并将其与单例模式结合起来。

Using the Code

要使用此代码,只需从基类继承即可。 派生类需要一个私有/受保护的构造函数,以确保无法直接实例化它,并且需要重写 GetItem 成员才能在对象不在缓存中时实际从某个位置获取该对象。

必须提供三种类型:

  1. T:继承 LazyLoadCacheBase 类的类的类型。
  2. TKey:键的类型。
  3. TValue:存储在缓存中的对象的类型。

这是该类:

/// <summary>
/// This base class can be inherited to implement a lazy load cache
/// </summary>
/// <typeparam name="T">Pass in the type of the derived class (the type of the class that 
/// inherits this base class)</typeparam>
/// <typeparam name="TKey">Type of the dictionary key objects</typeparam>
/// <typeparam name="TValue">Type of the dictionary value objects</typeparam>
internal abstract class LazyLoadCacheBase<T, TKey,
    TValue> where T: LazyLoadCacheBase<T, TKey, TValue>
{
    private Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();

    abstract protected TValue GetItem(TKey key);

    protected LazyLoadCacheBase()
    {
    }

    public static T Instance
    {
        get
        {
            return Creator.Singleton;
        }
    }

    public Dictionary<TKey, TValue> Dictionary
    {
        get { return _dictionary; }
        set {_dictionary = value;}
    }

    public TValue GetValue(TKey key)
    {
        if (!_dictionary.ContainsKey(key))
        {
            TValue item = GetItem(key);
            _dictionary.Add(key, item);
        }
        return _dictionary[key];
    }

    private sealed class Creator
    {
        private static readonly T _instance = (T)typeof(T).InvokeMember(typeof(T).Name,
            BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Instance,
            null, null, null);

        internal static T Singleton
        {
            get { return _instance; }
        }
    }

}

使用该类的一个例子:

internal class MyObjectCache: LazyLoadCacheBase<MyObjectCache, int, IMyObject %gt;
{
    // Prevent direct instantiation
    private MyObjectCache()
    {
    }

    protected override IMyObject GetItem(int key)
    {
        
        IMyObject item = GetMyObjectFromDB(key);
        return item;
    }
}

关注点

  • 为了维护派生类作为单例,它们需要具有私有或受保护的构造函数。 这就需要在实例化单例时使用反射。
  • 在我的实现中,我公开了内部字典,以防我想一次加载所有项目,并提供灵活性。 所需的功能实际上应该被封装(例如,LoadAll 方法)。
  • 我故意保持这个类非常简单。 如果您有其他要求,应该很容易自己添加它们。 例如,加载到缓存中的项目会一直保留到应用程序关闭。 显然,您可以包含一种基于过期时间或其他标准从缓存中删除项目的机制。

历史

  • 首次提交。
© . All rights reserved.