ASP.net HttpRuntime.Cache 使用的默认序列化是啥

Posted

技术标签:

【中文标题】ASP.net HttpRuntime.Cache 使用的默认序列化是啥【英文标题】:What is the default serialization used by the ASP.net HttpRuntime.CacheASP.net HttpRuntime.Cache 使用的默认序列化是什么 【发布时间】:2011-01-10 21:36:57 【问题描述】:

只是想知道是否有人明确知道 ASP.net HttpRuntime.Cache 使用的默认序列化是什么?是二进制、XML 还是其他?

我问是因为我有一种情况,我正在用相同自定义类型的多个对象填充一个通用列表。自定义类型是 POCO,没有什么特别之处。它的所有属性都是公开的 get;放; ,它是公共的,没有继承,没有接口。事实上,它比我们缓存的许多其他对象要简单得多,这些对象可以正常工作。我尝试将 [Serializable] 属性添加到自定义类,但没有效果。

我使用唯一键将列表添加到缓存中。该列表在插入缓存之前已被验证为已填充,列表中的对象也已被验证为已填充。但是当列表从缓存中拉出时,它是一个空列表(NOT NULL),它根本没有任何项目。这意味着该列表正在被添加到缓存中并且是可检索的,但由于某种原因,缓存在序列化列表中的对象时出现问题。

我只是觉得这很奇怪,因为我有另一个更复杂的自定义对象列表(包括继承、接口,还包含属性,这些属性是其他复杂对象的通用列表)并且这些列表的缓存无需问题。

工作和非工作列表都在消耗缓存数据的 ASP.net 用户控件之外的 C# 类中进行管理。这两个缓存处理类都调用完全相同的缓存管理器类单例实例,该实例包装了 HttpRuntime.Cache 以提供用于将对象拉入和推送到缓存中的类型化方法。

任何人都知道可能导致这种情况发生的原因。我唯一能想到的是 Document 对象的“Blurb”属性可能包含 html,但如果 ASP.net 对缓存使用二进制序列化,我看不出这将如何做任何事情。

这是课程

public class Document

    public string ContentTypeId  get; set; 
    public string ContentId  get; set; 
    public bool IsCustom  get; set; 
    public Language DocLanguage  get; set; 
    public string RegularTitle  get; set; 
    public string InvertedTitle  get; set; 
    public string Blurb  get; set; 
  

这是语言属性中使用的子类

public class Language

    public string Name  get; set; 
    public string Code  get; set; 

【问题讨论】:

【参考方案1】:

根据 Reflector,HttpRuntime.Cache 根本不序列化数据,它只是将其存储在内存中的 Hashtable 中。

您说您将对缓存的调用包装在您自己的单例对象中。你为什么这么做? HttpRuntime.Cache 是一个静态属性,所以你的包装方法也可以是静态的。

【讨论】:

这是一个公司网络应用程序,是由比我更有权力的人做出的架构决策:)。 除非你有相反的证据,否则我会怀疑 ASP.NET 运行时之前的包装代码。我自己编写了这种架构代码(包括我自己的缓存包装器!),而且我知道要做好是多么困难。也许您碰巧以一种并非旨在处理的方式使用它?我建议与您的包装类的作者讨论此事。【参考方案2】:

关于发生这种缓存异常的环境的更多细节。

我有一个 ASP.net 用户控件,它代表页面上的选项卡式容器。此控件包含用户选择的主题列表。对于用户选择的每个主题,此控件都会为该主题创建一个新选项卡,其中包含与该主题相关的文档。

控件通过利用 ASP.net 提供的 LoadControl 方法创建新选项卡。然后它从其列表中为新创建的选项卡控件分配一个主题。每个选项卡控件都知道如何为其分配的主题定位文档。

在此选项卡控件中实现了缓存。用于缓存文档列表的缓存键对于查看该主题的用户的 Site+Topic+Gender+Age 是完全唯一的。这允许符合该标准的所有用户在站点上缓存和检索文档列表。

当文档列表被传递到缓存时,它们是通过常规的旧对象引用传递的(即列表文档 = _documents)。但是当从缓存中拉出时,列表是空的。

虽然每个选项卡控件都是同一用户控件的自己的实例,并且选项卡控件中使用的所有变量都是该控件的私有变量,并且应该特定于该控件。我已经走到了尽头,尽管各个选项卡不可能覆盖彼此的私人列表,但我决定一定有某种疯狂的参考错误正在发生,如果是这样的话,我需要停止使用缓存中的引用对象,只向缓存发送我试图存储的列表的全新副本。

然后我对 List 使用了以下扩展方法,并在每个列表被传递到缓存时克隆了它们。这使得传递到缓存的所有项目都是全新的对象,它们在内存中拥有自己的空间,并拥有对该内存的唯一引用。

已修复。缓存现在起作用了。列表现在完全按照它们添加到缓存中的方式返回。我不知道为什么这会有所作为,如果有人有任何想法我很想听听。

    /// <summary>
    /// Clones the specified list to clone.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="listToClone">The list to clone.</param>
    /// <returns></returns>
    public static IList<T> Clone<T>(this IList<T> listToClone) where T : ICloneable
    
        return listToClone.Select(item => (T)item.Clone()).ToList();
    

【讨论】:

【参考方案3】:

缓存通常不会序列化或克隆您放入其中的对象。它们只是将一个键与您传入的对象相关联。由于列表是引用类型,因此当您使用该键从缓存中检索时,您对列表所做的任何更改都是可见的。所以我的猜测是你在插入后从列表中删除项目。这就是插入时的克隆解决它的原因。

【讨论】:

以上是关于ASP.net HttpRuntime.Cache 使用的默认序列化是啥的主要内容,如果未能解决你的问题,请参考以下文章

asp.net 自带的缓存

ASP.net HttpRuntime.Cache 使用的默认序列化是啥

asp.net 缓存Cache的使用总结

HttpRuntime.Cache

Asp.net中的Cache--HttpRuntim.Cache 和 HttpContext.Current.Cache

我应该使用 HttpRuntime.Cache 吗?