在类库中正确实现缓存以在asp.net应用程序中使用

时间:2020-03-06 14:57:49  来源:igfitidea点击:

我正在asp.net应用程序中使用的类库中实现缓存。

我使用静态方法将缓存对象创建为单例模式,以更新缓存,实际上只是将成员变量/属性与我需要缓存的数据集合一起加载(当然需要一些锁定逻辑)。我认为这是一个不错的方法,因为我可以通过以下方式访问我的数据:

MyCacheObject.Instance.MyDataCollection

我正在创建一个新的缓存对象,以存储由某个键分区的大量数据。我的意思是我正在创建一个新的缓存,但是该缓存不会一次加载所有数据,而是为每个访问的键存储一个集合。

MyOtherCacheObject.Instance.MyOtherDataCollection(indexkey)

这次提出了有关垃圾回收的问题。由于我存储了大量的数据,如果突然之间进行了gc操作,那不是浪费吗?由于这只是单例模式,因此无法确保数据保留在缓存中。

所以我的问题是实现缓存以处理这种情况的最佳实践是什么?我真的不喜欢这个庞大的复杂解决方案,而且我知道System.Web中有缓存,但是这似乎有点"错位",因为这只是一个类库,或者我们怎么看?

解决方案

只要缓存仍然保留对数据的引用,就不会收集垃圾数据。

另外,永远不要使用Singletons。

我认为,最佳解决方案将具有以下特征:

  • 使用平台提供的可用缓存服务,以避免编写自己的缓存服务。
  • 不要将类库耦合到System.Web,以使各层保持一致。
  • 但是,如果类库在ASP.NET应用程序中运行,则该解决方案不需要引入其他缓存实现(例如,企业库缓存应用程序块),这需要其他配置和设置。

因此,我将使用IoC策略,以允许类库根据运行的环境使用不同的缓存实现。

假设我们将抽象缓存协定定义为:

public interface ICacheService 
{
    AddItem(...);
}

我们可以提供基于System.Web的实现:

public AspNetBasedCacheService : ICacheService
{
    AddItem(...)
    {
        // Implementation that uses the HttpContext.Cache object
    }
 }

然后将该实现"发布"为单例。请注意,与原始方法的不同之处在于,单例只是对基于ASP.NET缓存服务的实现的引用,而不是完整的"缓存对象"。

public class ChacheServiceProvider 
{
    public static IChacheService Instance {get; set;}

}

我们将必须通过执行延迟初始化或者在应用程序启动时(在global.asax.cs中)来初始化chaching实现。

而且每个域组件都将能够使用已发布的缓存服务,而无需知道它是基于System.Web实现的。

// inside your class library:
IChacheService chache = CacheServiceProvider.Instance;
cache.AddItem(...);

我同意这可能不是最简单的解决方案,但是我的目标是在不牺牲代码解耦和灵活性的情况下利用ASP.NET缓存实现。

希望我能正确理解问题。