Wie implementieren Sie eine generische cache-manager in c#
Ich versuche, die Implementierung eines generischen cache-manager, aber ich bin nicht sicher, wie Sie gehen über das tun der Verriegelung.
Habe ich die folgenden so weit, aber wenn ich zwei cache-Einträge mit der gleichen Rückgabetypen, dann ich vermute, das gleiche lock-Objekt verwendet werden würde!
public class CacheManager : ICacheManager
{
static class TypeLock<T>
{
public static readonly object SyncLock = new object();
}
private readonly ICache _cache;
public CacheManager(ICache cache)
{
if (cache == null)
throw new ArgumentNullException("cache");
_cache = cache;
}
public TResult AddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
return AddCache(cacheKey, null, acquire, cacheDurationInMinutes);
}
public TResult AddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
var entry = acquire.Invoke();
if (entry != null)
{
if (dependency != null)
_cache.InsertWithDependency(cacheKey, entry, dependency, DateTime.Now.AddMinutes(cacheDurationInMinutes));
else
_cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
}
return entry;
}
public TResult GetOrAddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
return GetOrAddCache(cacheKey, null, acquire, cacheDurationInMinutes);
}
public TResult GetOrAddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
{
var entry = _cache.GetItem(cacheKey) as TResult;
if (entry == null)
{
lock (TypeLock<TResult>.SyncLock)
{
entry = _cache.GetItem(cacheKey) as TResult;
if (entry == null)
{
entry = acquire.Invoke();
if (entry != null)
{
if (dependency != null)
_cache.InsertWithDependency(cacheKey, entry, dependency,
DateTime.Now.AddMinutes(cacheDurationInMinutes));
else
_cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
}
}
}
}
return entry;
}
}
Jede Hilfe wäre sehr geschätzt werden!
- Irgendein besonderer Grund, warum Sie nicht wollen, zu verwenden, etwas aus dem System.- Laufzeit.Caching-namespace?
- Ich Baue auf SharePoint 2010, also leider .net 3.5 framework.
- Das ist schade...
- Was ist das eigentliche problem, das Sie konfrontiert sind?
- Wie es aussieht, die gleiche lock-Objekt verwendet werden, für jede cache-Einträge mit dem gleichen return-Typ, während ich nur mit der lock auf den gleichen cache-Eintrag
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie richtig, dies würde die Verwendung der gleichen Sperre für alle cache-Einträge des gleichen Typs. Halten Sie die eigentliche caching-Methode (Speicher, Datei, Datenbank,...) unabhängig von dieser cache-manager, schlage ich vor, die Speicherung ein extra sync-Objekt für jeden cache-Eintrag, damit Ihre cache-Einträge Aussehen wird, wie zum Beispiel
Tuple<object, TResult>
statt nurTResult
, wo dieobject
wird einnew object()
für jeden Eintrag ein und werden für die Verriegelung.ICacheManager
- interface würde die gleiche bleiben, aber in der Umsetzung (d.h.CacheManager
Klasse) würden Sie verwenden eine modifizierteICache
- Schnittstelle, die hätte setzen nicht nur [key, value] Paaren, aber auch mit einem sync-Objekt für jedes solches paar.DieTuple
version war nur eine schnelle Idee, es wäre besser, erstellen Sie eine Art vonCacheEntry
Objekt, das enthalten würdeValue
undSyncObject
Eigenschaften. Was würde das bedeuten, dass in Ihrem code, die Sie verwenden könnenvar entry = _cache.GetItem(cacheKey)
und verwenden Sie dannif(entry != null) lock (entry.SyncObject) { ... }
BlockingCollection<TCacheKey>
(oder anderen thread-sichere collection) zu sehen, welche Schlüssel werden dem cache Hinzugefügt. Dann, anstelle von sperren Sie können den neuen Schlüssel in dieser Sammlung, fügen Sie den entsprechenden Eintrag aus dem cache, dann entfernen Sie den Schlüssel aus der Sammlung.Sollten Sie nie sperren Sie in Ihre caching-code, es sei denn, es ist wirklich notwendig.
Verwenden Gleichzeitigen Wörterbuch, wenn Sie nicht möchten, verwenden alle bekannten cache.
Ich würde auch sagen, Sie sollten wahrscheinlich verwenden Sie die
System.Runtime.MemorCache
statt.Oder verwenden Sie eine Lösung, die nicht Abstrakt für Sie,
wie mein CacheManager https://github.com/MichaCo/CacheManager 😉
Ich bin nicht sicher, dass Sie verwenden sollten, Schloss, alos, warum nicht MemoryCache statt ICache-Schnittstelle? Ist das nicht die Speicher-cache-generisch genug?
Warum hast du die Kraft, die cache Zeit in Minuten, die Sie passieren soll, eine Zeitspanne, um Ihre cache-Methoden, ich wäre mehr Generika.
Ich umgesetzt eine version von einem cache-manager vor einigen Monaten, aber es war web orientiert.