zoukankan      html  css  js  c++  java
  • 一个简单的变量替换型模版

    这个是为了Micolog.Net的“主题预编译”制作的模版工具。主要负责简单的模版替换,以及在模版文件中调用C#方法。

    Micolog.Net 的主题机制采用的是XML的数据+XSLT转码生成HTML。在一个博客系统中,有很多设置,比如博客名称等是不经常更换的,与其在每次生成html时都从XML中转换,不如直接在选择主题时直接对这些设置进行替换。考虑到主题应有的扩展性,这个模版机制采用“注入方法”的方式实现。

    首先看一个最简单的例子:

                var template = new Micolog.Common.Template.Simple();
                template.LoadString("Hi,I'm {$Username}");
                template.Parameters.Add("Username", "Soar、毅");
                template.Process();
                Console.WriteLine(template.ToString());
                //将输出 Hi,I'm Soar、毅
    

    其次,有时候,我们会需要对传入的参数格式化,比如输出按照一定格式的日期:

                var template = new Micolog.Common.Template.Simple();
                template.LoadString("Hi,I'm {$Username} And Now Is {$Now:yyyy年MM月dd日}");
                template.Parameters.Add("Username", "Soar、毅");
                template.Parameters.Add("Now", DateTime.Now);
                template.Process();
                Console.WriteLine(template.ToString());
                //将输出 Hi,I'm Soar、毅 And Now Is 2012年08月24日
    

    在做到这一步的时候,这个简单的模版引擎算是差不多了。可是还缺少点什么:扩展。因为一个博客模版在安装完成后,可能需要进行一些自定义的设置。这些设置就要通过另一个方法来完成了。这个就是,动态的调用方法,通过传入不同的参数实现扩展,并且可以定义默认值:

                var template = new Micolog.Common.Template.Simple();
                template.LoadString("Hi,I'm {$Username} And Now Is {$Now:yyyy年MM月dd日}\n1 + 1 = {$Add(1,1)}\n{$NotDifine(1,1),默认值}");
                template.Parameters.Add("Username", "Soar、毅");
                template.Parameters.Add("Now", DateTime.Now);
                template.Methods.Add("Add", (arg) => 
                {
                    if (arg == null || arg.Length != 2) return "参数不正确!";
                    return (Convert.ToInt32(arg[0]) + Convert.ToInt32(arg[1])).ToString();
                });
                template.Process();
                Console.WriteLine(template.ToString());
                //将输出
                //Hi,I'm Soar、毅 And Now Is 2012年08月24日
                //1 + 1 = 2
                //默认值
    

    简单的引擎就是简单的引擎,不带有IF判断,For循环等。但是功能够用了。至少在Micolog.Net中够用了。模版采取的方式是正则表达式,除了,正则部分有点复杂之外,其他的还好。代码如下:

    源代码
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Text;
      4 using System.IO;
      5 using System.Text.RegularExpressions;
      6 using NewLife.Reflection;
      7 
      8 namespace Micolog.Common.Template
      9 {
     10     /// <summary>
     11     /// 简易模板,实现简单的模板替换
     12     /// </summary>
     13     /// <remarks>
     14     /// 简单变量替换:{$Date}
     15     /// 格式变量替换:{$Date:yyyy-MM-dd}
     16     /// 方法调用替换:{$GetDate(1,2,3),100}{$GetDate(1,2)}
     17     /// 方法调用格式替换:{$GetDate(1,2,3):0.00,100}{$GetDate(1,2):0.00}
     18     /// </remarks>
     19     public class Simple
     20     {
     21         private static readonly Regex SimpleTagReg = new Regex(@"\{\$(\w+)\}");
     22         private static readonly Regex FormatTagReg = new Regex(@"\{\$(\w+):([\w|\.]+)\}");
     23         private static readonly Regex MethodTagReg = new Regex(@"\{\$(\w+)\(([\w|,]+)\),([\w|\.]+)}");
     24         private static readonly Regex MethodFormatTagReg = new Regex(@"\{\$(\w+)\(([\w|,]+)\):([\w|\.]+),([\w|\.]+)}");
     25         private static readonly Regex MethodNotDefaultTagReg = new Regex(@"\{\$(\w+)\(([\w|,]+)\)}");
     26         private static readonly Regex MethodFormatNotDefaultTagReg = new Regex(@"\{\$(\w+)\(([\w|,]+)\):([\w|\.]+)}");
     27         private StringBuilder template;
     28         private String _Body;
     29         /// <summary>
     30         /// 模板内容
     31         /// </summary>
     32         public String Body
     33         {
     34             get 
     35             {
     36                 return _Body; 
     37             }
     38             set 
     39             {
     40                 _Body = value;
     41                 this.template = new StringBuilder(value);
     42             }
     43         }
     44         ///// <summary>
     45         ///// 输出模板内容
     46         ///// </summary>
     47         ///// <returns></returns>
     48         //public override string ToString()
     49         //{
     50         //    return this._Body;
     51         //}
     52         private Dictionary<String,Object> _Parameters;
     53         /// <summary>
     54         /// 编译参数
     55         /// </summary>
     56         public Dictionary<String,Object> Parameters
     57         {
     58             get 
     59             {
     60                 if (_Parameters == null)
     61                 {
     62                     lock (typeof(Simple))
     63                     {
     64                         if (_Parameters == null)
     65                         {
     66                             _Parameters = new Dictionary<String, Object>();
     67                         }
     68                     }
     69                 }
     70                 return _Parameters; 
     71             }
     72         }
     73 
     74         private Dictionary<String, Func<String[], Object>> _Methods;
     75         /// <summary>
     76         /// 编译方法
     77         /// </summary>
     78         public Dictionary<String, Func<String[], Object>> Methods
     79         {
     80             get
     81             {
     82                 if (_Methods == null)
     83                 {
     84                     lock (typeof(Simple))
     85                     {
     86                         _Methods = new Dictionary<String, Func<String[], Object>>();
     87                     }
     88                 }
     89                 return _Methods;
     90             }
     91         }
     92         
     93         /// <summary>
     94         /// 载入模板文件
     95         /// </summary>
     96         /// <param name="path"></param>
     97         public void Load(String path)
     98         {
     99             this.Load(path, Encoding.UTF8);
    100         }
    101         /// <summary>
    102         /// 载入模板文件,并制定编码方式
    103         /// </summary>
    104         /// <param name="path"></param>
    105         /// <param name="encoding"></param>
    106         public void Load(String path, Encoding encoding)
    107         {
    108             using (var sr = new StreamReader(path, encoding))
    109             {
    110                 this._Body = sr.ReadToEnd();
    111                 this.template = new StringBuilder(this._Body);
    112             }
    113         }
    114         /// <summary>
    115         /// 载入模板字符串
    116         /// </summary>
    117         /// <param name="body"></param>
    118         public void LoadString(String body)
    119         {
    120             this._Body = body;
    121             this.template = new StringBuilder(body);
    122         }
    123 
    124         /// <summary>
    125         /// 编译模板
    126         /// </summary>
    127         public void Process()
    128         {
    129             //Regex
    130             if (this._Parameters == null) return;
    131             var map = new Dictionary<String,String>();
    132             //处理简单标签
    133             foreach (Match match in SimpleTagReg.Matches(this._Body))
    134             {
    135                 var tag = match.Groups[0].Value;
    136                 var name = match.Groups[1].Value;
    137                 if (this._Parameters.ContainsKey(name) && !map.ContainsKey(tag))
    138                 {
    139                     //如果参数中包含这个标签,就将这个标签加入缓存
    140                     map.Add(tag, this._Parameters[name].ToString());
    141                 }
    142             }
    143             //处理格式化标签
    144             foreach (Match match in FormatTagReg.Matches(this._Body))
    145             {
    146                 var tag = match.Groups[0].Value;
    147                 var name = match.Groups[1].Value;
    148                 var format = match.Groups[2].Value;
    149                 if (this._Parameters.ContainsKey(name) && !map.ContainsKey(tag))
    150                 {
    151                     map.Add(tag, String.Format("{0:" + format + "}", this._Parameters[name]));
    152                 }
    153             }
    154             //处理方法标签
    155             foreach (Match match in MethodTagReg.Matches(this._Body))
    156             {
    157                 var tag = match.Groups[0].Value;
    158                 var method = match.Groups[1].Value;
    159                 var parameters = match.Groups[2].Value;
    160                 var defaultValue = match.Groups[3].Value;
    161                 if (!map.ContainsKey(tag))
    162                 {
    163                     if (this._Methods.ContainsKey(method))
    164                     {
    165                         var value = this._Methods[method](parameters.Split(',')).ToString();
    166                         map.Add(tag, value);
    167                     }
    168                     else
    169                     {
    170                         map.Add(tag, defaultValue);
    171                     }
    172                 }
    173             }
    174             foreach (Match match in MethodFormatTagReg.Matches(this._Body))
    175             {
    176                 var tag = match.Groups[0].Value;
    177                 var method = match.Groups[1].Value;
    178                 var parameters = match.Groups[2].Value;
    179                 var format = match.Groups[3].Value;
    180                 var defaultValue = match.Groups[4].Value;
    181                 if (!map.ContainsKey(tag))
    182                 {
    183                     if (this._Methods.ContainsKey(method))
    184                     {
    185                         var value = this._Methods[method](parameters.Split(','));
    186                         map.Add(tag, String.Format("{0:" + format + "}", value));
    187                     }
    188                     else
    189                     {
    190                         map.Add(tag, defaultValue);
    191                     }
    192                 }
    193             }
    194             foreach (Match match in MethodNotDefaultTagReg.Matches(this._Body))
    195             {
    196                 var tag = match.Groups[0].Value;
    197                 var method = match.Groups[1].Value;
    198                 var parameters = match.Groups[2].Value;
    199                 if (!map.ContainsKey(tag))
    200                 {
    201                     if (this._Methods.ContainsKey(method))
    202                     {
    203                         var value = this._Methods[method](parameters.Split(',')).ToString();
    204                         map.Add(tag, value);
    205                     }
    206                     else
    207                     {
    208                         map.Add(tag, String.Empty);
    209                     }
    210                 }
    211             }
    212             foreach (Match match in MethodFormatNotDefaultTagReg.Matches(this._Body)) // .Matches(this._Body))
    213             {
    214                 var tag = match.Groups[0].Value;
    215                 var method = match.Groups[1].Value;
    216                 var parameters = match.Groups[2].Value;
    217                 var format = match.Groups[3].Value;
    218                 var defaultValue = match.Groups[4].Value;
    219                 if (!map.ContainsKey(tag))
    220                 {
    221                     if (this._Methods.ContainsKey(method))
    222                     {
    223                         var value = this._Methods[method](parameters.Split(','));
    224                         map.Add(tag, String.Format("{0:" + format + "}", value));
    225                     }
    226                     else
    227                     {
    228                         map.Add(tag, defaultValue);
    229                     }
    230                 }
    231             }
    232             foreach (var i in map)
    233             {
    234                 this.template.Replace(i.Key, i.Value);//替换模板内容
    235             }
    236         }
    237         /// <summary>
    238         /// 保存处理结果
    239         /// </summary>
    240         /// <param name="path"></param>
    241         public void SaveAs(String path)
    242         {
    243             this.SaveAs(path, Encoding.UTF8);
    244         }
    245         /// <summary>
    246         /// 保存处理结果并制定编码方式
    247         /// </summary>
    248         /// <param name="path"></param>
    249         /// <param name="encoding"></param>
    250         public void SaveAs(String path, Encoding encoding)
    251         {
    252             if (this.template == null) throw new Exception("还未载入模板!");
    253             using (var sw = new StreamWriter(path, false, encoding))
    254             {
    255                 sw.Write(this.template.ToString());
    256             }
    257         }
    258         public override string ToString()
    259         {
    260             return this.template == null ? this._Body : this.template.ToString();
    261         }
    262     }
    263 }
  • 相关阅读:
    npm改为淘宝镜像
    html中table中td内容换行
    git 切换文件夹路径
    git经常使用的命令
    day16
    day15
    day13
    day14
    day12
    day11
  • 原文地址:https://www.cnblogs.com/Soar1991/p/2654851.html
Copyright © 2011-2022 走看看