为MemoryCache(或任何缓存)实现Generic Get <t>

时间:2016-04-07 04:02:58

标签: c# generics caching type-conversion memorycache

我试图写一个&#34;简单&#34; Generic Get<T>;延期 System.Runtime.MemoryCache

为什么&#34;简单&#34; ?因为我一般在缓存之前知道对象的真实类型,所以当我从缓存中检索它时,我不会以不可预测的方式转换它。

例如:if boolean&#34; true&#34; value存储在cacheKey&#34; id&#34;,所以

Get<string>("id") == "true";
Get<int>("id") == 1; // any result > 0 is okay
Get<SomeUnpredictableType> == null; // just ignore these trouble conversions

这是我未完成的实施:

public 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);
}

非常感谢任何建议。

===================================

更新(2016年11月4日):

对于那些很好的建议,我实现了我的第一个版本的Get&lt; T&gt;

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 ... */
}

2 个答案:

答案 0 :(得分:2)

提案:

echo '<li><img src=HERE_GOES_PATH_TO_YOUR_FOLDER/"'.$src.'"/></li>';

用法(假设您在缓存中有public 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; } 类型的ID):

int

我没有测试过。

答案 1 :(得分:2)

基本工作是编写CastValue&lt; T&gt;将任何对象转换为所需类型。并且它不必处理非常复杂的条件,因为缓存中的对象类型对于程序员是可预测的。这是我的版本。

public static T CastValue<T>(object value) {
    if (value == null || value is DBNull) {
        return default(T);
    }
    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);
}
相关问题