値キャッシュ機能の汎用基本クラスがあります。
public abstract class CachedValueProviderBase<T> : ICachedValueProvider<T> where T : class
{
private Cache Cache { set; get; }
protected string CacheKey { get; set; }
protected int CacheSpanInMinutes { get; set; }
private static readonly object _cacheLock = new object();
public T Values
{
get
{
T value = Cache[CacheKey] as T;
if (value == null)
{
lock (_cacheLock)
{
value = Cache[CacheKey] as T;
if (value == null)
{
value = InitializeCache();
}
}
}
return value;
}
}
protected CachedValueProviderBase()
{
Cache = HttpRuntime.Cache;
CacheSpanInMinutes = 15;
}
public T CacheValue(T value)
{
if (value != null)
{
lock (_cacheLock)
{
Cache.Insert(CacheKey, value, null, DateTime.UtcNow.AddMinutes(CacheSpanInMinutes),
Cache.NoSlidingExpiration);
}
}
return value;
}
private T InitializeCache()
{
T value = Initialize();
CacheValue(value);
return value;
}
protected abstract T Initialize();
}
この基本クラスを利用するクラスがいくつかありますが、Tが異なる限り問題ありません。たとえば、2つのサブクラスが同じT、文字列を使用する場合、それらは同じキャッシュロックオブジェクトを共有します。基本クラスにロジックを実装しながら、各サブクラスに独自のキャッシュロックオブジェクトを与える最良の方法は何ですか?
更新 以下の提案の後、クラスを更新しました。
public abstract class CachedValueProviderBase<T> : ICachedValueProvider<T> where T : class
{
private Cache Cache { set; get; }
protected string CacheKey { get; set; }
protected int CacheSpanInMinutes { get; set; }
private object _cacheLock = new object();
public T Values
{
get
{
T value = Cache[CacheKey] as T;
if (value == null)
{
lock (_cacheLock)
{
value = Cache[CacheKey] as T;
if (value == null)
{
value = InitializeCache();
}
}
}
return value;
}
}
protected CachedValueProviderBase()
{
Cache = HttpRuntime.Cache;
CacheSpanInMinutes = 15;
}
public T CacheValue(T value)
{
if (value != null)
{
Cache.Insert(CacheKey, value, null, DateTime.UtcNow.AddMinutes(CacheSpanInMinutes),
Cache.NoSlidingExpiration);
}
return value;
}
private T InitializeCache()
{
T value = Initialize();
CacheValue(value);
return value;
}
protected abstract T Initialize();
}
}
私のサブクラスはシングルトンになっているので、静的なcachelockオブジェクトを取り除き、インスタンス変数にすることができます。