Ich versuche, ein "einfache" Generisches Get für <T> Erweiterung System.Runtime.MemoryCache zu schreibenImplementieren Generisches Get <T> für Memory (oder einem Cache)
Warum "simple"? Da ich den realen Typ des Objekts im Allgemeinen kenne, bevor ich es zwischenspeichern kann, werde ich es, wenn ich es aus dem Cache abrufe, nicht auf unvorhersehbare Weise konvertieren.
Zum Beispiel: Wenn boolean Wert "true" im Cache mit CacheKey "id" gespeichert ist, so
Get<string>("id") == "true";
Get<int>("id") == 1; // any result > 0 is okay
Get<SomeUnpredictableType> == null; // just ignore these trouble conversions
Hier ist meine unvollständig UMSETZUNG:
pubic static T DoGet<T>(this MemoryCache cache, string key) {
object value = cache.Get(key);
if (value == null) {
return default(T);
}
if (value is T) {
return (T)value;
}
// TODO: (I'm not sure if following logic is okay or not)
// 1. if T and value are both numeric type (e.g. long => double), how to code it?
// 2. if T is string, call something like Convert.ToString()
Type t = typeof(T);
t = (Nullable.GetUnderlyingType(t) ?? t);
if (typeof(IConvertible).IsAssignableFrom(value.GetType())) {
return (T)Convert.ChangeType(value, t);
}
return default(T);
}
Irgendwelche Vorschläge sehr geschätzt werden.
===================================
Update (2016.04.11):
pubic static T DoGet<T>(this MemoryCache cache, string key)
{
object value = cache.Get(key);
if (value == null) {
return default(T);
}
// support for nullables. Do not waste performance with
// type conversions if it is not a nullable.
var underlyingType = Nullable.GetUnderlyingType(t);
if (underlyingType != null)
{
value = Convert.ChangeType(value, underlyingType);
}
return (T)value;
}
Usage (annehmen:
Für jene nette Anregungen gegeben, ich meine erste Version von Get <T>
public class MemCache {
private class LazyObject<T> : Lazy<T> {
public LazyObject(Func<T> valueFactory) : base(valueFactory) { }
public LazyObject(Func<T> valueFactory, LazyThreadSafetyMode mode) : base(valueFactory, mode) { }
}
private static T CastValue<T>(object value) {
if (value == null || value is DBNull) {
return default(T);
}
Type valType = value.GetType();
if (valType.IsGenericType && valType.GetGenericTypeDefinition() == typeof(LazyObject<>)) {
return CastValue<T>(valType.GetProperty("Value").GetValue(value));
}
if (value is T) {
return (T)value;
}
Type t = typeof(T);
t = (Nullable.GetUnderlyingType(t) ?? t);
if (typeof(IConvertible).IsAssignableFrom(t) && typeof(IConvertible).IsAssignableFrom(value.GetType())) {
return (T)Convert.ChangeType(value, t);
}
return default(T);
}
private MemoryCache m_cache;
public T Get<T>(string key) {
return CastValue<T>(m_cache.Get(key));
}
public void Set<T>(string key, T value, CacheDependency dependency) {
m_cache.Set(key, value, dependency.AsCacheItemPolicy());
}
public T GetOrAdd<T>(string key, Func<T> fnValueFactory, CacheDependency dependency) {
LazyObject<T> noo = new LazyObject<T>(fnValueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
LazyObject<T> old = m_cache.AddOrGetExisting(key, noo, dependency.AsCacheItemPolicy()) as LazyObject<T>;
try {
return CastValue<T>((old ?? noo).Value);
} catch {
m_cache.Remove(key);
throw;
}
}
/* Remove/Trim ... */
}
Sie könnten (T) Convert.ChangeType (Wert, Typof (T)) verwenden, aber dies wäre nur ein Teil Ihrer sehr generischen Methode. –
Danke, ich habe meinen Beispielcode hinzugefügt. Ich bin mir immer noch nicht sicher, ob es einige Bedingungen gibt, die ich in der TODO-Sektion verpasst habe. – ineztia
Schreiben Sie Komponententests, fügen Sie alle Fälle hinzu, die Sie behandeln möchten. –