Advertisement
tubededentifrice

C# MVC6 Views finder in assemblies

Jan 5th, 2015
794
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.58 KB | None | 0 0
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Reflection;
  8. using Microsoft.AspNet.FileSystems;
  9. using Microsoft.AspNet.Mvc;
  10. using Microsoft.AspNet.Mvc.Razor;
  11. using Microsoft.Framework.Expiration.Interfaces;
  12. using Microsoft.Framework.OptionsModel;
  13. using Microsoft.Framework.Runtime;
  14.  
  15. namespace MvcFs
  16. {
  17.     public class EmbeddedExpiringFileInfoCache:IFileSystem
  18.     {
  19.         private readonly ConcurrentDictionary<string,ExpiringFileInfo> _fileInfoCache=new ConcurrentDictionary<string,ExpiringFileInfo>(StringComparer.Ordinal);
  20.  
  21.         private readonly TimeSpan cacheDuration;
  22.         private readonly List<Assembly> assemblyList;
  23.  
  24.  
  25.         protected virtual IFileSystem FileSystem { get; }
  26.  
  27.         public EmbeddedExpiringFileInfoCache(IOptions<RazorViewEngineOptions> razorViewEngineOptions,ILibraryManager libraryManager)
  28.         {
  29.             //Defaults to DefaultRazorFileSystemCache which contains its own cache
  30.             //Could also be new PhysicalFileSystem(env.ApplicationBasePath); or razorViewEngineOptions.Options.FileSystem (as used in DefaultRazorFileSystemCache)
  31.             FileSystem=new DefaultRazorFileSystemCache(razorViewEngineOptions);
  32.            
  33.             //This is not relevant since Assemblies won't change over time; the cost to keep this is very low, so we just keep it
  34.             //razorViewEngineOptions.Options.ExpirationBeforeCheckingFilesOnDisk is only 2 seconds or so by default
  35.             cacheDuration=TimeSpan.FromDays(365);
  36.  
  37.             //Find all loadable assemblies
  38.             assemblyList=libraryManager.GetLibraries()
  39.                 .Select(_library => _library.Name)
  40.                 .Distinct()
  41.                 .SelectMany(_assemblyName => {
  42.                     //Only select loadable assemblies
  43.                     try
  44.                     { return new[] { Assembly.Load(new AssemblyName(_assemblyName)) }; }
  45.                     catch
  46.                     { return new Assembly[0]; }
  47.                 })
  48.                 .ToList();
  49.         }
  50.  
  51.         /// <inheritdoc />
  52.         public IFileInfo GetFileInfo(string virtualPath)
  53.         {
  54.             if(FileSystem!=null)
  55.             {
  56.                 //Ask the real FS first, so the user can override imported views
  57.                 IFileInfo fileInfo=FileSystem.GetFileInfo(virtualPath);
  58.                 if(fileInfo!=null && fileInfo.Exists)
  59.                 { return fileInfo; }
  60.             }
  61.  
  62.             //Look in our cache first
  63.             ExpiringFileInfo expiringFileInfo;
  64.             DateTime utcNow=DateTime.UtcNow;
  65.             if(_fileInfoCache.TryGetValue(virtualPath,out expiringFileInfo) && expiringFileInfo.ValidUntil>utcNow)
  66.             { return expiringFileInfo.FileInfo; }
  67.  
  68.             //Search in assemblies
  69.             string path=virtualPath.StartsWith("/")?virtualPath.Substring(1):virtualPath;
  70.             foreach(Assembly assembly in assemblyList)
  71.             {
  72.                 string name=assembly.GetManifestResourceNames().FirstOrDefault(_path => _path.Equals(path,StringComparison.OrdinalIgnoreCase));
  73.                 if(name!=null)
  74.                 {
  75.                     expiringFileInfo=new ExpiringFileInfo {
  76.                         FileInfo=new EmbeddedFileInfo(assembly,name/*,information*/),
  77.                         ValidUntil=utcNow.Add(cacheDuration)
  78.                     };
  79.                 }
  80.             }
  81.            
  82.             //Make sure we don't save a null (would cause problem above with cache check)
  83.             expiringFileInfo=expiringFileInfo??new ExpiringFileInfo {
  84.                 FileInfo=new NotFoundFileInfo(virtualPath),
  85.                 ValidUntil=utcNow.Add(cacheDuration)
  86.             };
  87.  
  88.             _fileInfoCache[virtualPath]=expiringFileInfo;
  89.             return expiringFileInfo.FileInfo;
  90.         }
  91.  
  92.         private class ExpiringFileInfo
  93.         {
  94.             public IFileInfo FileInfo { get; set; }
  95.             public DateTime ValidUntil { get; set; }
  96.         }
  97.  
  98.         public IDirectoryContents GetDirectoryContents(string subpath)
  99.         { return FileSystem.GetDirectoryContents(subpath); }
  100.     }
  101.  
  102.     public class EmbeddedFileInfo:IFileInfo,IDisposable
  103.     {
  104.         private Assembly assembly;
  105.         private Stream stream;
  106.  
  107.         public DateTime LastModified { get; }
  108.         public long Length { get; }
  109.         public string Name { get; }
  110.         public string PhysicalPath { get; }
  111.  
  112.         public bool IsDirectory => false;
  113.         public bool Exists => true;
  114.         public bool IsReadOnly => true;
  115.  
  116.         public EmbeddedFileInfo(Assembly assembly,string name/*,ILibraryInformation libraryInformation*/)
  117.         {
  118.             this.assembly=assembly;
  119.             stream=assembly.GetManifestResourceStream(name);
  120.  
  121.             Name=name;
  122.             LastModified=DateTime.UtcNow;
  123.             PhysicalPath=assembly.CodeBase;
  124.             Length =stream?.Length??0;
  125.         }
  126.  
  127.  
  128.         public Stream CreateReadStream()
  129.         { return stream; }
  130.  
  131.         public void WriteContent(byte[] content)
  132.         { throw new ReadOnlyException("This is readonly"); }
  133.  
  134.         public void Delete()
  135.         { throw new ReadOnlyException("This is readonly"); }
  136.  
  137.         public IExpirationTrigger CreateFileChangeTrigger()
  138.         { throw new ReadOnlyException("This is readonly"); }
  139.  
  140.         public void Dispose()
  141.         {
  142.             stream?.Dispose();
  143.             stream=null;
  144.         }
  145.     }
  146. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement