在HttpContext.Current.Items缓存中使用lambda表达式查找密钥

4

我有一个按需缓存,使用HttpContext.Current.Items实现,代码如下:

private static readonly Lazy<CacheCurrentCall> lazy =
    new Lazy<CacheCurrentCall>(() => new CacheCurrentCall());

public static CacheCurrentCall Instance
{
    get
    {
        IDictionary items = HttpContext.Current.Items;
        if (!items.Contains("CacheCurrentCall"))
        {
            items["CacheCurrentCall"] = new CacheCurrentCall();
        }
        return items["CacheCurrentCall"] as CacheCurrentCall;
    }
}

private CacheCurrentCall()
{

}

public void Add<T>(T o, string key, int cacheDurationSeconds = 0)
{
    HttpContext.Current.Items.Add(key, o);
}

public void Clear(string key)
{
    HttpContext.Current.Items.Remove(key);
}

public bool Exists(string key)
{
    return HttpContext.Current.Items[key] != null;
}

public bool Get<T>(string key, out T value)
{
    try
    {
        if (!Exists(key))
        {
            value = default(T);
            return false;
        }
        value = (T)HttpContext.Current.Items[key];
    }
    catch
    {
        value = default(T);
        return false;
    }
    return true;
}

现在我需要删除所有以特定字符串开头的键,因此我考虑使用以下方法:

public IEnumerable<string> GetKey (Func<string, bool> condition)

然后遍历结果并清除它们(我甚至可以在接受lambda表达式的Clear中直接清除,我猜)。但是,如果可能的话,我迷失在尝试实现这样一个方法上了。

有什么帮助吗?

谢谢

编辑:

Servy,我一直在尝试(盲目尝试一些事情,但更多或少地遵循这条路线)

public IEnumerable<string> GetKeys(Func<string, bool> condition)
{
    List<string> list = new List<string>();

    foreach (var key in HttpContext.Current.Items.Keys)
    {
        if (condition(key as string))
        {
            list.Add(key as string);
        }
    }

    return list;
}

但我得到了:

对象引用未设置为对象的实例

我现在要尝试一下p.s.w.g,因为它可能有效,而且在我看来更加优雅。

第二次编辑:

我需要稍微修改p.s.w.g的解决方案。我不是将字符串存储在缓存中,而是其他类型的对象,所以我现在使用这个。

public IEnumerable<string> GetKeys (Func<string, bool> condition)
{
    return HttpContext.Current.Items
        .Cast<DictionaryEntry>()
        .Where(e => e.Key is string && condition(e.Key as string))
        .Select(e => e.Key as string);
}

例如,清除缓存的调用如下:
public void ClearCache()
{
    var ownedItemSummaryKeys = CacheCurrentCall.Instance.GetKeys(k => k.Contains("OwnedItemSummaryCurrent"));

    foreach (var ownedItemSummaryKey in ownedItemSummaryKeys.ToList())
    {
        CacheCurrentCall.Instance.Clear(ownedItemSummaryKey);
    }
}

1
你尝试过什么吗?在实现这个解决方案时遇到了什么问题?你是否遇到了错误、输出不正确或其他问题? - Servy
1个回答

5

Items属性是一个IDictionary,因此您需要这样做:

public IEnumerable<string> GetKey (Func<string, bool> condition)
{
    return HttpContext.Current.Items
        .Cast<DictionaryEntry>()
        .Where(e => e.Key is string && 
                    e.Value is string && 
                    condition(e.Key as string))
        .Select(e => e.Value as string);
}

或者在查询语法中:

public IEnumerable<string> GetKey (Func<string, bool> condition)
{
    return
        from e in HttpContext.Current.Items.Cast<DictionaryEntry>()
        where e.Key is string && 
              e.Value is string && 
              condition(e.Key as string)
        select e.Value as string;
}

更新 我误读了问题。我以为你想根据键的某些标准选择。如果您只想选择键,那么实际上这要容易一些:

public IEnumerable<string> GetKey (Func<string, bool> condition)
{
    return HttpContext.Current.Items.Keys
        .OfType<string>()
        .Where(condition);
}

或者使用查询语法:

public IEnumerable<string> GetKey (Func<string, bool> condition)
{
    return
        from k in HttpContext.Current.Items.Keys.OfType<string>()
        where condition(k)
        select k;
}

谢谢,最终我需要对你的代码进行一些小改动(问题不是很清楚,是我的错)(请参见第二次编辑),但它可以工作。 - mitomed
@mitomed 对不起,我一开始误解了你的问题。请看我的更新答案,提供更好的解决方案。 - p.s.w.g

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接