优化-任何从样式/脚本捆绑包中获取所有包含的方法

本文关键字:获取 包中 包含 方法 任何 样式 脚本 优化 | 更新日期: 2023-09-27 17:59:31

我正在处理一些动态绑定,它根据配置添加CSS和JS文件。

我设计了一个新的StyleBundle,这样:

var cssBundle = new StyleBundle("~/bundle/css");

然后循环通过配置并添加任何找到的包含:

cssBundle.Include(config.Source);

在循环之后,我想检查是否真的包含了任何文件/目录。我知道有EnumerateFiles(),但我不认为这100%符合目的。

之前还有其他人做过类似的事情吗?

优化-任何从样式/脚本捆绑包中获取所有包含的方法

Bundle类使用一个内部项目列表,该列表不向应用程序公开,并且不一定可以通过反射访问(我尝试过,但无法获得任何内容)。您可以使用BundleResolver类获取有关此方面的一些信息,如:

var cssBundle = new StyleBundle("~/bundle/css");
cssBundle.Include(config.Source);
// if your bundle is already in BundleTable.Bundles list, use that.  Otherwise...
var collection = new BundleCollection();
collection.Add(cssBundle)
// get bundle contents
var resolver = new BundleResolver(collection);
List<string> cont = resolver.GetBundleContents("~/bundle/css").ToList();

如果你只需要计数,那么:

int count = resolver.GetBundleContents("~/bundle/css").Count();

编辑:使用反射

很明显,我之前的反射测试出了问题。

这实际上是有效的:

using System.Reflection;
using System.Web.Optimization;
...
int count = ((ItemRegistry)typeof(Bundle).GetProperty("Items", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(cssBundle, null)).Count;

当然,您可能应该在那里添加一些安全检查,就像许多反射示例一样,这违反了Items属性的预期安全性,但它确实有效。

您可以对Bundle使用以下扩展方法:

public static class BundleHelper
{
    private static Dictionary<Bundle, List<string>> bundleIncludes = new Dictionary<Bundle, List<string>>();
    private static Dictionary<Bundle, List<string>> bundleFiles = new Dictionary<Bundle, List<string>>();
    private static void EnumerateFiles(Bundle bundle, string virtualPath)
    {
        if (bundleIncludes.ContainsKey(bundle))
            bundleIncludes[bundle].Add(virtualPath);
        else
            bundleIncludes.Add(bundle, new List<string> { virtualPath });
        int i = virtualPath.LastIndexOf('/');
        string path = HostingEnvironment.MapPath(virtualPath.Substring(0, i));
        if (Directory.Exists(path))
        {
            string fileName = virtualPath.Substring(i + 1);
            IEnumerable<string> fileList;
            if (fileName.Contains("{version}"))
            {
                var re = new Regex(fileName.Replace(".", @"'.").Replace("{version}", @"('d+(?:'.'d+){1,3})"));
                fileName = fileName.Replace("{version}", "*");
                fileList = Directory.EnumerateFiles(path, fileName).Where(file => re.IsMatch(file));
            }
            else // fileName may contain '*'
                fileList = Directory.EnumerateFiles(path, fileName);
            if (bundleFiles.ContainsKey(bundle))
                bundleFiles[bundle].AddRange(fileList);
            else
                bundleFiles.Add(bundle, fileList.ToList());
        }
    }
    public static Bundle Add(this Bundle bundle, params string[] virtualPaths)
    {
        foreach (string virtualPath in virtualPaths)
            EnumerateFiles(bundle, virtualPath);
        return bundle.Include(virtualPaths);
    }
    public static Bundle Add(this Bundle bundle, string virtualPath, params IItemTransform[] transforms)
    {
        EnumerateFiles(bundle, virtualPath);
        return bundle.Include(virtualPath, transforms);
    }
    public static IEnumerable<string> EnumerateIncludes(this Bundle bundle)
    {
        return bundleIncludes[bundle];
    }
    public static IEnumerable<string> EnumerateFiles(this Bundle bundle)
    {
        return bundleFiles[bundle];
    }
}

然后简单地用Add():替换您的Include()呼叫

var bundle = new ScriptBundle("~/test")
    .Add("~/Scripts/jquery/jquery-{version}.js")
    .Add("~/Scripts/lib*")
    .Add("~/Scripts/model.js")
    );
var includes = bundle.EnumerateIncludes();
var files = bundle.EnumerateFiles();

如果您也在使用IncludeDirectory(),只需添加相应的AddDirectory()扩展方法即可完成此示例。