使用Redis和Service Stack为Piranha编写缓存提供程序 - 跟踪缓存的对象类型

时间:2014-02-27 09:17:51

标签: caching redis servicestack.redis piranha-cms

我正在编写一个缓存提供程序来缓存任何类型的对象。当我从缓存中读取值时,问题是转换为正确的类型。

using (var redisClient = redisClientsManager.GetClient())
{
    redisClient.Set(key, value, new TimeSpan(1, 0, 0));
}

因此将对象转换为缓存并将其转换为字符串非常容易。当我把它拉出缓存时,它就变得有趣了

 using (var redisClient = redisClientsManager.GetClient())
 {
     return redisClient.Get<object>(key);
 }

这不起作用,因为我们没有适当的类型来强制转换,所以默认是返回json字符串。

我在想,我应该为我的所有食人鱼对象创建一个哈希,然后有这样的东西

 piranha:cache id = "{ some json }"
 piranha:cache id:type = PAGETYPE

这样我就可以在将对象保存到缓存时设置对象类型。我想知道是否有更好的方法来获取/设置被缓存的对象类型?

理想情况下,代码会显式地进行转换,但目前redis中的缓存只使用对象类型(我认为)。


public object this[string key]
{
    get
    {
        using (var redisClient = redisClientsManager.GetClient())
        {
            if (redisClient.HashContainsEntry(PiranhaHash, key))
            {
                string resultJson = redisClient.GetValueFromHash(PiranhaHash, key);
                string objType = redisClient.GetValueFromHash(PiranhaHash, String.Format("{0}:Type", key));

                Type t = JsonConvert.DeserializeObject<Type>(objType);
                object result = JsonConvert.DeserializeObject(resultJson, t);

                return result;
            }
        }
        return null;
    }
    set
    {
        using (var redisClient = redisClientsManager.GetClient())
        {
            redisClient.SetEntryInHash(PiranhaHash, key, JsonConvert.SerializeObject(value));
            redisClient.SetEntryInHash(PiranhaHash, String.Format("{0}:Type", key), JsonConvert.SerializeObject(value.GetType()));
        }
    }
}

在大多数情况下,此实现应该有效,但Page对象不会正确地从Json反序列化,并且控制器将始终为null。我认为必须进行一些后端更改才能实现这一目标。

1 个答案:

答案 0 :(得分:1)

由于目前不同缓存提供程序的数量非常有限,我们总是可以更改提供程序接口,以便从长远来看能够更好地工作。我也有一些关于使Get操作通用以清理访问缓存的代码的想法。

从长远来看,也许这个界面会更好:

/// <summary>
/// Gets the cached model for the given key.
/// </summary>
/// <typeparam name="T">The model type</typeparam>
/// <param name="key">The unique key</param>
/// <returns>The model</returns>
T Get<T>(string key);

/// <summary>
/// Sets the cached model for the given key.
/// </summary>
/// <param name="key">The unique key</param>
/// <param name="obj">The model</param>
void Set(string key, object obj);

/// <summary>
/// Removes the cached model for the given key.
/// </summary>
/// <param name="key">The unique key</param>
void Remove(string key);

由于此类更改将导致核心存储库中的批次更新,因此我必须在单独的分支中实施它以进行测试,您可以使用它来实现提供程序。


修改

我仔细查看了Page对象,字段Controller, View, Redirect, IsPublished & IsStartpage是没有set访问器的计算属性。此字段不应序列化为JSON。正在使用哪个序列化程序以及可以使用哪些属性来使序列化程序忽略属性(如ScriptIgnore)。

此外,属性TemplateController, TemplateView, TemplateRedirect & TemplateName具有私有集访问器,我不知道这是否是使用JSON序列化程序的问题。

此致

哈坎