9

Pracuję z dynamicznym pakietowaniem, który dodaje pliki CSS i JS na podstawie konfiguracji.Web.Optimizations - w jaki sposób uzyskać wszystkie elementy z zestawu stylów/skryptów?

spin nowy StyleBundle takie, że:

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

następnie pętli config i dodać dowolną Znaleziony obejmuje:

cssBundle.Include(config.Source); 

Po pętli Chcę sprawdzić, czy nie było właściwie żadnych plików/katalogi włączone. Wiem, że istnieje EnumerateFiles(), ale nie sądzę, że to 100% służy celowi.

Ktoś jeszcze zrobił coś podobnego wcześniej?

Odpowiedz

13

Klasa Bundle wykorzystuje wewnętrzną listę przedmiotów, które nie są narażone na działanie aplikacji , a niekoniecznie jest dostępny za pośrednictwem refleksji (próbowałem i nie może dostać żadnych treści) . Można pobrać pewne informacje na ten temat używając klasa BundleResolver tak:

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(); 

Jeśli wystarczy licznik następnie:

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

EDIT: przy użyciu odbicia

Widocznie zrobiłem coś źle z moim testem odbicia wcześniej.

To rzeczywiście działa:

using System.Reflection; 
using System.Web.Optimization; 

... 

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

Należy prawdopodobnie dodać kilka kontroli bezpieczeństwa istnieje oczywiście, i jak wiele przykładów odbicia ten narusza zamierzonego bezpieczeństwa mienia Items, ale robi pracy.

+0

Dzięki Corey, że wygląda dobrze, tylko kwestią jest to, że pakiet jest dodawany do kolekcji, aby jej zawartość była zliczana. Najlepiej byłoby sprawdzić zawartość, aby upewnić się, że jest> 0 PRZED dodaniem do kolekcji. Czy to ma sens? – timothyclifford

+0

Możesz użyć przykładu odbicia, aby uzyskać liczbę lub utworzyć nową (i tymczasową) kolekcję, tak jak to zrobiłem w początkowym przykładzie kodu powyżej i użyć 'BundleResolver', aby uzyskać listę załączonych plików. Pakiet nie będzie dostępny dla reszty systemu, dopóki nie dodasz go do kolekcji 'BundleTable.Bundles', więc możesz użyć dowolnej metody, aby sprawdzić pakiet, zanim stanie się ogólnie dostępny. – Corey

+0

Czy jednak nie jest to ItemRegistry? – timothyclifford

1

Można stosować następujące metody rozszerzenie dla 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]; 
    } 
} 

Następnie wystarczy zastąpić połączeniami Include() z Add():

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(); 

Jeśli są również za pomocą IncludeDirectory(), tylko kompletne przykład, dodając odpowiednią metodę rozszerzenia AddDirectory().

+1

Metoda "EnumerateFiles" jest faktycznie wbudowana w klasę Bundle. Zwróci listę obiektów BundleFile, która daje dostęp nie tylko do ścieżki każdego pliku, ale także do pliku IItemTransform (ów), jeśli są stosowane. – Triynko