<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      由淺入深:自己動手開發(fā)模板引擎——解釋型模板引擎(二)

      受到群里兄弟們的竭力邀請,老陳終于決定來分享一下.NET下的模板引擎開發(fā)技術。本系列文章將會帶您由淺入深的全面認識模板引擎的概念、設計、分析和實戰(zhàn)應用,一步一步的帶您開發(fā)出完全屬于自己的模板引擎。關于模板引擎的概念,我去年在百度百科上錄入了自己的解釋(請參考:模板引擎)。老陳曾經(jīng)自己開發(fā)了一套網(wǎng)鳥Asp.Net模板引擎,雖然我自己并不樂意去推廣它,但這已經(jīng)無法阻擋群友的喜愛了!

      概述

      本課我們主要討論“命令解釋器”的實現(xiàn)。命令就是指令,指令也是構成更加復雜的模板引擎的基本元素之一。至此我們可以歸納出來,模板引擎在工作的過程中,首先將字符流轉(zhuǎn)換為Token流,然后再將Token流轉(zhuǎn)換為Element集合(也算是流),然后將特定的Element單獨拿出來或組合在一起形成指令、語句等。寫一個模板引擎,和寫一個小型的編譯器幾乎相當,因此我們需要耐心、細心!

      目標

      解析并運行如下模板代碼結構:

      1. /_Page_Footer.shtml
      2. /_Page_Header.shtml
      3. /_Public_Footer.shtml
      4. /_Public_Header.shtml
      5. /Index.shtml

      文件"/_Page_Footer.shtml"包含的代碼:

      <!--#include file="_Public_Footer.shtml" -->

      文件"/_Page_Header.shtml"包含的代碼:

      <!--#include file="_Public_Header.shtml" -->

      文件"/_Public_Footer.shtml"包含的代碼:

      </body>
      </html>

      文件"/_Public_Header.shtml"包含的代碼:

      <!DOCTYPE HTML>
      <html>
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <title>{UserName}的博客</title>
      </head>
      <body>

      文件"/Index.shtml"包含的代碼:

      1 <!--#include file="_Page_Header.shtml" -->
      2 <ul>
      3 <li>博主姓名:{UserName}</li>
      4 <li>創(chuàng)建日期:{CreationTime:yyyy年MM月dd日 HH:mm:ss}</li>
      5 <li>粉絲數(shù)量:{FunsCount:D4}</li>
      6 </ul>
      7 <!--#include file="_Page_Footer.shtml" -->

      今天的模板內(nèi)容被切分成了5個部分,嵌套層次達到了3層,解析難度比較大。實際上在編寫本文之前,我自己的解釋型模板引擎在內(nèi)部是使用正則表達式的方式來實現(xiàn)嵌套指令解析的。不過,我們今天不會這么做了!

      使用正則表達式實現(xiàn)

      本節(jié)課的目的是說明命令解釋器的實現(xiàn),本著循序漸進的原則,我們首先考慮使用正則表達式來實現(xiàn)“<!--#include file="_Page_Header.shtml" -->”命令,在以后的課程中我們將會學習更加復雜的代碼解析方法。

      我們需要按照順序使用正則表達式遞歸的讀取和合并代碼文檔,具體實現(xiàn)如下:

       1 /// <summary>
       2 /// 表示 #Include 命令解釋器。
       3 /// </summary>
       4 public static class IncludeCommandParser
       5 {
       6     private static int _nestedCount;
       7 
       8     /// <summary>
       9     /// 處置包含文檔。
      10     /// </summary>
      11     /// <param name="templateString">包含模板代碼的字符串。</param>
      12     /// <param name="basePath">處置包含命令時要使用的基準路徑。</param>
      13     /// <returns>返回 <see cref="string"/></returns>
      14     public static string Parse(string templateString, string basePath)
      15     {
      16         if (String.IsNullOrWhiteSpace(templateString)) return String.Empty;
      17         if (String.IsNullOrWhiteSpace(basePath)) return templateString;
      18 
      19         if (Directory.Exists(basePath) == false) throw new DirectoryNotFoundException();
      20 
      21         return _ProcessSSIElement(templateString, basePath);
      22     }
      23 
      24     private static string _ProcessSSIElement(string templateString, string basePath)
      25     {
      26         if (_nestedCount > 10) return templateString;
      27 
      28         var matches = Regex.Matches(templateString, @"<!--#include file=""([^""]+)""\s*-->", RegexOptions.IgnoreCase | RegexOptions.Singleline);
      29 
      30         foreach (Match match in matches)
      31         {
      32             var file = new FileInfo(Path.Combine(basePath, match.Groups[1].Value.Replace('/', '\\')));
      33 
      34             if (file.Exists == false) continue;
      35 
      36             var subTemplate = File.ReadAllText(file.FullName).Trim();
      37 
      38             subTemplate = _ProcessSSIElement(subTemplate, Path.GetDirectoryName(file.FullName));
      39 
      40             templateString = templateString.Replace(match.Groups[0].Value, subTemplate);
      41         }
      42 
      43         _nestedCount++;
      44 
      45         return templateString;
      46     }
      47 }

      測試代碼:

       1 [Test]
       2 public void LoadFileTest()
       3 {
       4     var fileName = Path.Combine(Environment.CurrentDirectory, "Templates\\Index.shtml");
       5 
       6     Assert.AreEqual(File.Exists(fileName), true);
       7 
       8     this._templateString = File.ReadAllText(fileName);
       9 
      10     Assert.NotNull(this._templateString);
      11 
      12     Trace.WriteLine(this._templateString);
      13 
      14     Assert.Greater(this._templateString.IndexOf("{CreationTime:yyyy年MM月dd日 HH:mm:ss}", StringComparison.Ordinal), 0);
      15 }
      16 
      17 [Test]
      18 public void ProcessTest()
      19 {
      20     this.LoadFileTest();
      21 
      22     Trace.WriteLine("本次輸出:");
      23 
      24     var basePath = Path.Combine(Environment.CurrentDirectory, "Templates");
      25     var templateEngine = TemplateEngine.FromString(this._templateString, basePath);
      26 
      27     templateEngine.SetVariable("url", "http://www.ymind.net/");
      28     templateEngine.SetVariable("UserName", "陳彥銘");
      29     templateEngine.SetVariable("title", "陳彥銘的博客");
      30     templateEngine.SetVariable("FunsCount", 98);
      31     templateEngine.SetVariable("CreationTime", new DateTime(2012, 4, 3, 16, 30, 24));
      32 
      33     var html = templateEngine.Process();
      34     Trace.WriteLine(html);
      35 }

      運行結果:

       1 <!--#include file="_Page_Header.shtml" -->
       2 <ul>
       3     <li>博主姓名:{UserName}</li>
       4     <li>創(chuàng)建日期:{CreationTime:yyyy年MM月dd日 HH:mm:ss}</li>
       5     <li>粉絲數(shù)量:{FunsCount:D4}個</li>
       6 </ul>
       7 <!--#include file="_Page_Footer.shtml" -->
       8 
       9 本次輸出:
      10 <!DOCTYPE HTML>
      11 <html>
      12 <head>
      13 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      14 <title>陳彥銘的博客</title>
      15 </head>
      16 <body>
      17 <ul>
      18     <li>博主姓名:陳彥銘</li>
      19     <li>創(chuàng)建日期:2012年04月03日 16:30:24</li>
      20     <li>粉絲數(shù)量:0098個</li>
      21 </ul>
      22 </body>
      23 </html>


      運行結果達到了我們的期望值!

      總結和代碼下載

      本課只是簡單的介紹命令解釋器的實現(xiàn)思路,實際上還有其他很多辦法可以實現(xiàn)。

      從下節(jié)課開始,我們將會接觸到更多代碼標記的解析方式,每篇博文篇幅不會太長,但一定會挑重點、擊中要害!

      本節(jié)課的內(nèi)容較為簡單,不提供代碼下載。


      模板引擎系列教程的規(guī)模比原來預想的還要龐大,因為我不想僅僅帖出各種代碼就了事,希望能從更多的角度給大家分享。因此,該系列文章以后全部劃入周末寫作。平時只寫文字性內(nèi)容,或小篇幅技術文章。

      希望大家能夠諒解!

      posted @ 2012-04-15 10:21  O.C  閱讀(4168)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 亚洲最大成人av在线天堂网| 岛国最新亚洲伦理成人| 亚洲日韩av无码一区二区三区| 97久久久亚洲综合久久| 亚洲免费成人av一区| 超碰伊人久久大香线蕉综合| 亚洲精品一区二区毛豆| 台北县| 青青草无码免费一二三区| 另类 专区 欧美 制服丝袜| 亚洲精品不卡av在线播放| 日本深夜福利在线观看| 国产国产午夜福利视频| 成人国产精品中文字幕| 久久精品午夜视频| 日韩无矿砖一线二线卡乱| 欧洲美熟女乱又伦AV影片| 亚欧美闷骚院| 久久月本道色综合久久| 亚洲人妻一区二区精品| 亚洲精品色哟哟一区二区| 成年女人黄小视频| 日韩中文字幕亚洲精品一| 国产aⅴ夜夜欢一区二区三区| 中文日产幕无线码一区中文| 国产精品美女自慰喷水| 日韩在线视频一区二区三| 亚洲中文字幕日产无码成人片| 日本一区二区不卡精品| 久久亚洲国产精品久久| 欧美大胆老熟妇乱子伦视频| 亚洲一区二区中文av| 国产精品欧美亚洲韩国日本久久| 亚洲最大成人av在线天堂网| 国产一区二区三区黄色片| 国产成人午夜福利在线播放| 在线A级毛片无码免费真人| 日韩乱码人妻无码系列中文字幕| 色一乱一伦一图一区二区精品| 亚洲一区二区三区在线| 亚洲国产美女精品久久久|