zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    再次或多次格式化导致namenode的ClusterID和datanode的ClusterID之间不一致的问题解决办法
    Linux安装aria2
    POJ 3335 Rotating Scoreboard 半平面交
    hdu 1540 Tunnel Warfare 线段树 区间合并
    hdu 3397 Sequence operation 线段树 区间更新 区间合并
    hud 3308 LCIS 线段树 区间合并
    POJ 3667 Hotel 线段树 区间合并
    POJ 2528 Mayor's posters 贴海报 线段树 区间更新
    POJ 2299 Ultra-QuickSort 求逆序数 线段树或树状数组 离散化
    POJ 3468 A Simple Problem with Integers 线段树成段更新
  • 原文地址:https://www.cnblogs.com/lwme/p/1725784.html
Copyright © 2011-2022 走看看