• StringTemplate.Net 学习笔记(9):深入了解模板组文件


    上文展示了简单的模板组文件语法,本文来更详细的了解模板组文件的语法。

    本文假设已经在应用程序启动时设置了默认的模板组loader(详细看上一篇):

    	void Application_Start(object sender, EventArgs e)
    	{
    		StringTemplateGroup.RegisterGroupLoader(new LWMEGroupLoader(AppDomain.CurrentDomain.BaseDirectory, null));
    	}

    1、注释

    这里的注释是指模板组文件的注释,它不同于模板文件的注释,仅仅用于在模板组文件内(模板之外),它们是:

    1. //单行注释
    2. /**/多行注释

    示例:

    	group test;
    	//单行模板组文件注释
    	/*多行
    	模板组文件
    	注释*/
    	t1() ::= <<
    		<!模板之内注释语法不变!>
    	>>
    	//单行模板组文件注释
    	/*多行
    	模板组文件
    	注释*/
    	t2() ::= <<
    		<!模板之内注释语法不变!>
    	>>

    2、模板的内容换行及缩进

    与模板文件一样,模板组内的模板同样会清除内容两边的空格。如:

    	foo() ::= <<
    	rodent
    	>>

    	foo() ::= "rodent"

    是一样的。但是在多行模板中换行,它会保持换行符,如:

    	foo() ::= <<
    	
    	2nd line is not blank, but first is
    	>>

    	foo() ::= <<<\n>
    	same as before; newline then this line
    	>>

    再如:

    	foo() ::= <<
    	rodent
    	
    	>>

    	foo() ::= <<
    	rodent<\n>
    	>>

    此方法同样适用于模板文件,也可以通过实现IStringTemplateWriter接口或继承AutoIndentWriter类来定制模板内容的缩进。

    3、模板参数

    在模板定义中,每一个参数都必须明确的定义在参数列表中,否则在调用setAttribute的时候会出错,例如定义以下模板:

    	group test;
    	t1(): <<
    		<arg>
    	>>

    当调用SetAttribute("arg", "test")时,会报错,不调用SetAttribute("arg", "test")则不会,感觉这个限制应该再严格一点。

    参数对默认值的支持,这个与sql server的存储过程参数类似,定义如下模板组(bin\debug\templates\test.stg),当未传递arg2时使用arg2的默认值:

    	group test;
    
    	t1(arg1,arg2="参数2") ::= <<
    		<arg1> <arg2>
    	>>

    当调用的代码为:

    	StringTemplateGroup g = StringTemplateGroup.LoadGroup("Templates/test");
    	StringTemplate st = g.GetInstanceOf("t1");
    	st.SetAttribute("arg1", "参数1");
    	st.SetAttribute("arg2", "参数2");
    	Console.WriteLine(st.ToString());
    	输出:参数1 参数2

    当注释掉st.SetAttribute("arg2", "参数2"); 时:

    	输出:参数1 参数2默认值

    它同样支持从匿名模板获取默认值,把模板组定义改成:

    	group test;
    
    	t1(arg1, arg2={arg2默认值}) ::= <<
    		<arg1> <arg2>
    	>>

    同样适用,但若仅仅只是这样的话倒是没太多意义,或许是我还没找到使用的方法。

    4、模板作为参数

    ST支持模板作为参数传递,定义模板组:

    	group test;
    
    	t1(arg1) ::= <<
    		<arg1>
    	>>
    	
    	t2(arg1) ::= <<
    		<arg1>
    	>>

    调用代码:

    	StringTemplateGroup g = StringTemplateGroup.LoadGroup("Templates/test");
    	StringTemplate st1 = g.GetInstanceOf("t1");
    	StringTemplate st2 = g.GetInstanceOf("t2");
    	st1.SetAttribute("arg1", st2);
    	st2.SetAttribute("arg1", "test");
    	Console.WriteLine(st1.ToString());
    	输出:	test

    但假如把st2.SetAttribute("arg1", "test")改成st2.SetAttribute("arg1", st1),而且开启了LintMode时(StringTemplate.LintMode = true,在调试的时候使用的)将会引起递归调用,参考http://www.antlr.org/wiki/display/ST/Template+and+attribute+lookup+rules

    5、Maps

    模板组文件支持一种字典(key/value)类型,稍微有点不同的是它还定义一个默认值,先看例子(调用代码省略):

    	group test;
    	
    	dict ::= [
    		"int" : "0",
    		"long" : "00",
    		"float" : "0.0",
    		"bool" : "false",
    		"first" : "1",
    		default : "null"
    	]
    
    	t1() ::= <<
    		<dict.int> <dict.float> <dict.none> <dict.("first")>
    	>>
    	输出:0 0.0 null 1

    从上面例子可以看出,当访问Maps不存在的key时,会返回它的默认值定义;对于保留字,它同样需要使用dict.("reserveword")来访问。

    Maps也可以通过代码访问,它返回的是一个HashTable实例:

    	StringTemplateGroup g = StringTemplateGroup.LoadGroup("Templates/test");			
    	IDictionary map = g.GetMap("dict");
    	foreach(DictionaryEntry entry in map) {
    		Console.WriteLine("{0} {1}", entry.Key, entry.Value);
    	}

    输出:

    	float 0.0
    	first 1
    	_default_ null
    	bool false
    	long 00
    	int 0

    既然是集合类型,那么同样能够在模板组文件里遍历:

    	group test;
    	
    	mapIterator() ::= <<
    	    <dict.keys:{key| 键:<key> 值:<dict.(key)>};separator=",">
    	    <\n>
    	    <dict.values:{value | <value>};separator=",">
    	>>

    输出:

        键:float 值:0.0,键:first 值:1,键:_default_ 值:null,键:bool 值:fa
    lse,键:long 值:00,键:int 值:0
    
        0.0,1,null,false,00,0

    不过,default也输出来了...

    Maps是一个很好的特性,使用它可以轻松的实现多语言化,如:

    中文界面

    	dict ::= [
    		"file" : "打开文件",
    		"close" : "关闭文件",
    		"exit" : "退出",
    		default : "未定义"
    	]

    英文界面

    	dict ::= [
    		"file" : "open file",
    		"close" : "close file",
    		"exit" : "exit",
    		default : "undefined"
    	]

    通过不同的区域设置来加载不同的语言文件。当然,还可以用于其他类似场景。

    本篇就到此为止吧,继承及接口放到下篇。

    本文地址:http://www.cnblogs.com/lwme/archive/2010/05/01/1725784.html

    参考:http://www.antlr.org/wiki/display/ST/Group+Files

  • 相关阅读:
    Django项目总结:Model高级
    Django项目总结:Response和Cookie
    数据库:索引
    数据库:视图
    数据库:约束
    MySQL:常用命令
    MySQL:安装和连接
    时间戳和正则表达式
    Java 类的概念与使用
    JAVA复习题
  • 原文地址:https://www.cnblogs.com/lwme/p/1725784.html
Copyright © 2020-2023  润新知