第四篇 基于.net搭建热插拔式web框架(RazorEngine实现)_html/css_WEB-ITnose
在开头也是先给大家道个歉,由于最近准备婚事导致这篇文章耽误了许久,同时也谢谢老婆大人对我的支持。
回顾上篇文章,我们重造了一个controller,这个controller中用到了视图引擎,我们的视图引擎虽然也叫Razor,但此Razor非mvc中的Razor,MVC中的Razor同样依赖于HttpContext,我们实现的Razor借用 RazorEngine 。关于 RazorEngine的更多介绍请参阅http://antaris.github.io/RazorEngine/。
在上篇文章中无论是View方法还是PartialView方法,都用到了CompileView对象,我们先来看一下 CompileView类的实现。
/// <summary> /// 视图编译类 /// </summary> public class CompileView { private static Regex layoutEx = new Regex("Layout\\s*=\\s*@?\"(\\S*)\";");//匹配视图中的layout static InvalidatingCachingProvider cache = new InvalidatingCachingProvider(); static FileSystemWatcher m_Watcher = new FileSystemWatcher(); static CompileView() { var config = new TemplateServiceConfiguration(); config.BaseTemplateType = typeof(HuberImplementingTemplateBase<>); config.ReferenceResolver = new HuberReferenceResolver(); config.CachingProvider = cache; cache.InvalidateAll(); Engine.Razor = RazorEngineService.Create(config); //添加文件修改监控,以便在cshtml文件修改时重新编译该文件 m_Watcher.Path = HuberVariable.CurWebDir; m_Watcher.IncludeSubdirectories = true; m_Watcher.Filter = "*.*"; m_Watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName; m_Watcher.Created += new FileSystemEventHandler(OnChanged); m_Watcher.Changed += new FileSystemEventHandler(OnChanged); m_Watcher.Deleted += new FileSystemEventHandler(OnChanged); m_Watcher.EnableRaisingEvents = true; } //当视图被修改后清除缓存 private static void OnChanged(object sender, FileSystemEventArgs e) { if (e.FullPath.EndsWith(".cshtml")) { string s = e.FullPath.Replace(HuberVariable.CurWebDir, "/"); var key = Engine.Razor.GetKey(s); cache.InvalidateCache(key); } } public CompileView() { } public string RunCompile(ITemplateKey key, Type modelType, object model, DynamicViewBag viewBag) { //判断唯一视图的缓存 string path = (HuberVariable.CurWebDir + key.Name).Replace(@"\\", @"\"); ICompiledTemplate cacheTemplate; cache.TryRetrieveTemplate(key, null, out cacheTemplate); if (cacheTemplate == null || !cacheTemplate.Key.Name.Trim().Equals(key.Name.Trim())) { CompileViewAndLayout(key, null, model, viewBag); } //当缓存存在返回结果 return Engine.Razor.RunCompile(key, null, model, viewBag); } /// <summary> /// 编译视图和层layout /// </summary> /// <param name="key">视图的唯一路径</param> /// <param name="modelType">视图类型 :视图/layout</param> /// <param name="model">页面 MODEL</param> /// <param name="viewBag">viewBag</param> public void CompileViewAndLayout(ITemplateKey key, Type modelType, object model, DynamicViewBag viewBag) { //获取视图 string FullPath = (HuberVariable.CurWebDir + key.Name.Replace("/", @"\")).Replace(@"\\", @"\"); string content = System.IO.File.ReadAllText(FullPath); //匹配layout var matchs = layoutEx.Matches(content); string layoutPath = string.Empty; if (matchs != null) { foreach (Match m in matchs) { layoutPath = m.Groups[1].Value; } } if (layoutPath != string.Empty) { //添加layout到模板 string FullLayoutPath = (HuberVariable.CurWebDir + layoutPath.Replace("/", @"\")).Replace(@"\\", @"\"); if (File.Exists(FullLayoutPath)) { ITemplateKey layoutKey = Engine.Razor.GetKey(layoutPath, ResolveType.Layout); CompileViewAndLayout(layoutKey, null, model, viewBag); } } if (key.TemplateType == ResolveType.Layout) { Engine.Razor.AddTemplate(key, content); } else { //编译视图 Engine.Razor.RunCompile(content, key, null, model); } } }
InvalidatingCachingProvider是RazorEngine对视图文件编译结果的一种缓存策略,RazorEngine提供的缓存策略还有DefaultCachingProvider,也可以自己实现一种缓存策略只要继承ICachingProvider。
HuberImplementingTemplateBase:我们自定义的一种Razor模板标签,如“@Html.Raw”,这个例子也可以在RazorEngine官方文档中找到。我们还可以按照规则定义更多用法,下边是我的一些实现:
1 /// <summary>页面帮助类 2 /// A simple helper demonstrating the @Html.Raw 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public class HuberImplementingTemplateBase<T> : TemplateBase<T> 6 { 7 /// <summary> 8 /// A simple helper demonstrating the @Html.Raw 9 /// </summary> 10 public HuberImplementingTemplateBase() 11 { 12 Html = new RazorHtmlHelper(); 13 } 14 15 /// <summary> 16 /// A simple helper demonstrating the @Html.Raw 17 /// 18 /// </summary> 19 public RazorHtmlHelper Html { get; set; } 20 21 } 22 23 public class RazorHtmlHelper 24 { 25 26 /// <summary> 27 /// 调用Action视图 28 /// </summary> 29 /// <param name="actionName">action方法名称</param> 30 /// <param name="controllerName">控制器名称</param> 31 /// <returns></returns> 32 public IEncodedString Action(string actionName, string controllerName) 33 { 34 return Action(actionName, controllerName, new { }); 35 36 } 37 38 /// <summary> 39 /// 调用Action视图 40 /// </summary> 41 /// <param name="actionName"></param> 42 /// <param name="controllerName"></param> 43 /// <param name="routeValues">传入参数</param> 44 /// <returns></returns> 45 public IEncodedString Action(string actionName, string controllerName, object routeValues) 46 { 47 RefRequestEntity paras = SetParamValue(routeValues); 48 49 var t = HuberHttpModule.CurDomainAssembly.GetType(HuberHttpModule.CurDomainAssemblyName + ".Controllers." + controllerName + "Controller"); 50 var m = t.GetMethod(actionName); 51 object dObj = Activator.CreateInstance(t); 52 object result = m.Invoke(dObj, new object[] { paras }); 53 return new RawString((result as RefRespondEntity).ResultContext.ToString()); 54 } 55 56 /// <summary> 57 /// 根据model设置传入参数 58 /// </summary> 59 /// <param name="routeValues"></param> 60 /// <returns></returns> 61 private static RefRequestEntity SetParamValue(object routeValues) 62 { 63 RefRequestEntity paras = new RefRequestEntity(); 64 65 Type t1 = routeValues.GetType(); 66 PropertyInfo[] pis = t1.GetProperties(); 67 foreach (PropertyInfo pi in pis) 68 { 69 paras.Request.Add(pi.Name, pi.GetValue(routeValues)); 70 71 } 72 return paras; 73 } 74 75 76 public IEncodedString RenderAction(string actionName, string controllerName) 77 { 78 return Action(actionName, controllerName, new { }); 79 } 80 81 public IEncodedString RenderAction(string actionName, string controllerName, object routeValues) 82 { 83 return Action(actionName, controllerName, routeValues); 84 } 85 86 public IEncodedString RenderPartial(string partialViewName, string controllerName) 87 { 88 return RenderPartial(partialViewName, controllerName, new { }, new DynamicViewBag()); 89 } 90 91 // Renders the partial view with the given view data and, implicitly, the given view data's model 92 public IEncodedString RenderPartial(string partialViewName, string controllerName, DynamicViewBag ViewBag) 93 { 94 return RenderPartial(partialViewName, controllerName, new { }, ViewBag); 95 } 96 97 // Renders the partial view with an empty view data and the given model 98 public IEncodedString RenderPartial(string partialViewName, string controllerName, object model) 99 {100 return RenderPartial(partialViewName, controllerName, model, new DynamicViewBag());101 }102 103 104 // Renders the partial view with a copy of the given view data plus the given model105 /// <summary>106 /// 部分视图107 /// </summary>108 /// <param name="partialViewName">部分视图名称</param>109 /// <param name="controllerName">控制器名称</param>110 /// <param name="model"> model</param>111 /// <param name="ViewBag">ViewBag</param>112 /// <returns></returns>113 public IEncodedString RenderPartial(string partialViewName, string controllerName, object model, DynamicViewBag ViewBag)114 {115 116 117 RefRequestEntity paras = SetParamValue(model);118 119 var t = HuberHttpModule.CurDomainAssembly.GetType(HuberHttpModule.CurDomainAssemblyName + ".Controllers." + controllerName + "Controller");120 var ActionFunc = t.GetMethod(partialViewName);121 object dObj = Activator.CreateInstance(t);122 123 var AddViewBageFunc = t.GetMethod("AddViewBageValues");124 125 foreach (string key in ViewBag.GetDynamicMemberNames())126 {127 128 AddViewBageFunc.Invoke(dObj, new object[] { key, Impromptu.InvokeGet(ViewBag, key) });129 }130 131 object result = ActionFunc.Invoke(dObj, new object[] { paras });132 return new RawString((result as RefRespondEntity).ResultContext.ToString());133 }134 135 }View Code
HuberReferenceResolver:我们定义的Razor中用的类库依赖。
1 public class HuberReferenceResolver : IReferenceResolver 2 { 3 4 static List<CompilerReference> compilerReference; 5 static HuberReferenceResolver() 6 { 7 //加载本地所有类库,@using 使用 8 compilerReference = new List<CompilerReference>(); 9 IEnumerable<string> loadedAssemblies = (new UseCurrentAssembliesReferenceResolver())10 .GetReferences(null, null)11 .Select(r => r.GetFile())12 .ToArray();13 foreach (var l in loadedAssemblies)14 {15 compilerReference.Add(CompilerReference.From(l));16 }17 18 19 20 }21 22 public string FindLoaded(IEnumerable<string> refs, string find)23 {24 return refs.First(r => r.EndsWith(System.IO.Path.DirectorySeparatorChar + find));25 }26 public IEnumerable<CompilerReference> GetReferences(TypeContext context, IEnumerable<CompilerReference> includeAssemblies)27 {28 29 #region 加载依赖程序集 此处是加载所有程序集,效率需要改进30 31 return compilerReference;32 #endregion33 }34 }View Code
CompileViewAndLayout()是编译视图文件的主要部分,其中有路径的转换、key的定义规则等。
获取视图文件对应编译后的缓存key: Engine.Razor.GetKey();
编译模板文件(即layout部分): Engine.Razor.AddTemplate();
编译视图文件: Engine.Razor.RunCompile()。
转载请注明出处:http://www.cnblogs.com/eric-z/p/5102718.html

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Le cache de mise à jour de la page Web du compte officiel, cette chose est simple et simple, et elle est suffisamment compliquée pour en boire un pot. Vous avez travaillé dur pour mettre à jour l'article officiel du compte, mais l'utilisateur a toujours ouvert l'ancienne version. Dans cet article, jetons un coup d'œil aux rebondissements derrière cela et comment résoudre ce problème gracieusement. Après l'avoir lu, vous pouvez facilement faire face à divers problèmes de mise en cache, permettant à vos utilisateurs de toujours ressentir le contenu le plus frais. Parlons d'abord des bases. Pour le dire franchement, afin d'améliorer la vitesse d'accès, le navigateur ou le serveur stocke des ressources statiques (telles que des images, CSS, JS) ou du contenu de la page. La prochaine fois que vous y accédez, vous pouvez le récupérer directement à partir du cache sans avoir à le télécharger à nouveau, et il est naturellement rapide. Mais cette chose est aussi une épée à double tranchant. La nouvelle version est en ligne,

L'article discute de l'utilisation des attributs de validation de formulaire HTML5 comme les limites requises, motifs, min, max et longueurs pour valider la saisie de l'utilisateur directement dans le navigateur.

L'article examine les meilleures pratiques pour assurer la compatibilité des navigateurs de HTML5, en se concentrant sur la détection des fonctionnalités, l'amélioration progressive et les méthodes de test.

Cet article démontre un ajout de bordure PNG efficace aux pages Web à l'aide de CSS. Il soutient que CSS offre des performances supérieures par rapport à JavaScript ou à des bibliothèques, détaillant comment ajuster la largeur, le style et la couleur des bordures pour un effet subtil ou proéminent

L'article traite du HTML & lt; Datalist & GT; élément, qui améliore les formulaires en fournissant des suggestions de saisie semi-automatique, en améliorant l'expérience utilisateur et en réduisant les erreurs. COMMANDE COMPRES: 159

L'article traite du HTML & lt; mètre & gt; élément, utilisé pour afficher des valeurs scalaires ou fractionnaires dans une plage, et ses applications courantes dans le développement Web. Il différencie & lt; mètre & gt; De & lt; Progress & gt; et ex

Cet article explique le html5 & lt; time & gt; élément de représentation sémantique de date / heure. Il souligne l'importance de l'attribut DateTime pour la lisibilité à la machine (format ISO 8601) à côté du texte lisible par l'homme, stimulant AccessIbilit

L'article traite du HTML & lt; Progress & GT; élément, son but, son style et ses différences par rapport au & lt; mètre & gt; élément. L'objectif principal est de l'utiliser & lt; Progress & gt; pour l'achèvement des tâches et & lt; mètre & gt; pour stati
