首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CacheDependency和路径依赖项的VirtualPathProvider

CacheDependency和路径依赖项的VirtualPathProvider
EN

Stack Overflow用户
提问于 2014-07-28 14:34:47
回答 1查看 819关注 0票数 1

我们在BundleTransformer MVC 4安装程序中使用ASP.NET库。我们的web应用程序是一个相当薄的层,所有服务器逻辑都在后端服务中处理。

安装完后,所有资源都将沿着web应用程序安装在文件系统上,但出于更新的原因,我们需要能够从服务中为JavaScript和CSS (较少的)资源提供服务--然后它们将覆盖本地(文件系统)版本。

本质上,如果从服务中获得,我们将从那里提供所请求的资源。如果没有,我们回到文件系统并从那里服务文件。

这一切都很有魅力,然后我们引入了LESS和@import语句,现在事情已经不那么好了。

我们仍然希望在Http中缓存较少转换的结果,而且每当依赖项发生变化时,我们都希望使该结果无效。VirtualPathProvider中的当前实现可以做到这一点,但是如果我更新单个文件(例如JavaScript文件),它将不会被更新。

我的VirtualPathProvider看起来是这样的:

代码语言:javascript
复制
public class ViewsAndScriptsPathProvider : VirtualPathProvider {

    private static IApplicationServiceResourcesManager ResourceManager {
        get { return InstanceProvider.Get<IApplicationServiceResourcesManager>(); }
    }

    public override bool FileExists(string virtualPath) {
        var exists = ResourceManager.Exists(virtualPath);
        return exists || base.FileExists(virtualPath);
    }

    public override VirtualFile GetFile(string virtualPath) {
        VirtualFile file;
        if (ResourceManager.TryGet(virtualPath, out file)) {
            return file;
        }
        return base.GetFile(virtualPath);
    }

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) {
        bool isRelevant = ResourceManager.IsRelevant(virtualPath);
        if (isRelevant) {
            var cachekeys = virtualPathDependencies.Cast<string>().Where(dependency => virtualPath != dependency).ToArray();
            return new CacheDependency(null, cachekeys);
        }
        if (IsBundle(virtualPath)) {
            return new CacheDependency(null, new[] { ResourceManager.ComponentCacheKey }, utcStart);
        }
        return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
    }

    private bool IsBundle(string virtualPath) {
        return virtualPath.StartsWith("~/bundles/", StringComparison.InvariantCultureIgnoreCase)
               || virtualPath.StartsWith("~/css/", StringComparison.InvariantCultureIgnoreCase);
    }

    public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) {
        byte[] bhash;
        string filehash;
        if (ResourceManager.TryGetFileHash(virtualPath, out bhash)) {
            filehash = BitConverter.ToString(bhash);
        } else {
            filehash = Previous.GetFileHash(virtualPath, virtualPathDependencies);
        }
        return filehash;
    }
}

将ResourceManager视为服务的代理/缓存。

我最大的问题是,我不完全理解CacheDependency的工作。如果我添加一个包含virtualPath本身的cachekey (第二个参数),那么服务器中就会有一个无限循环。如果我简单地返回null,那么它将不适用于较少的@imports

如果有人能够解释或指出VirtualPathProvider应该如何实现GetCacheDependency和GetFileHash函数,我可能能够解决这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-09 14:52:25

实际上,我在一段时间前已经想出了一个解决方案,这与HttpCache与CacheDependency对象的工作方式有关。然而,这是相当复杂的。

基本上,我有三种方案:

  1. 资源仅托管在文件系统上。
  2. 资源仅托管在服务中。
  3. 资源托管在服务和本地文件系统中。

对于1.我使用CacheDependency对象作为文件位置。这是标准的,默认情况下是VirtualPathProvider的工作方式。

对于2.我使用一个自定义(派生) ResourceCacheDependency,它实现了在代理有新版本时使自己失效的逻辑。

对于3.我使用AggregateCacheDependency对象,它具有物理文件的CacheDependency和ResourceCacheDependency对象。

对于所有虚拟路径依赖项(资源的依赖项列表),我重复上述假设,并将其构建到AggreateCacheDependency中(它可能有很多依赖项)。

在VirtualPathProvider的自定义实现中,我重写了GetCacheDependency方法,以便根据上面的分析返回相关的CacheDependency对象。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24997636

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档