最近我在做一个CMS系统,需要一个模板引擎,选择了NVelocity,NVelocity是JAVA的开源模板引擎Velocity移植到了.NET平台,这个不过多介绍。因为Velocity的模板语法很简单我就选用了它作为我们CMS的模板引擎。NVelocity好像是Castle Project维护的,我在Castle Project的网站找到了入门文章,看上去是比较简单的,很容易上手。然后我就照着他的例子编码:
var props = new ExtendedProperties();
props.Add(RuntimeConstants.INPUT_ENCODING, "utf-8");
props.Add(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
props.Add(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, targetViewFolder);
velocityEngine.Init(props);
props.Add那三句在例子中是没有的,是我自作聪明加上去的,因为如果不传入配置的话会按照NVelocity的默认配置,但是这么写是错的,为什么是错的稍后告诉大家。
这段代码编译过去了,然后运行到这里也没有出问题,但是我在velocityEngine.GetTemplate的时候却出了问题,报异常说找不到资源,经过断点调试发现了诡异的地方
为什么我的配置没有生效,反而还是默认的设置?然后我又在网上找了一些例子,由于“老眼昏花”,并没有看出到底错在哪里,最后没办法我觉得需要追踪一下NVelocity的源代码,我在Castle Project的网站上下载整套源码,其中有NVelocity的代码,但是项目缺少directive.properties和nvelocity.properties连个文件,我先项目中去掉了这个文件,发现虽然可以顺利编译,但是在使用NVelocity的时候连默认配置都没有了,我只好在已经编译好的NVelocity.dll中取得了这个两个文件(以前还不知道怎么取DLL中的资源文件,又研究了N久),最后编译成功,单步调适,跟着Init(props)方法进去看个究竟,果然发现了奇怪的地方:
p.Keys怎么可能一个元素都没有?其实在监视props变量里面是有东东的,但是Keys里什么都没有,然后我通过分析ExtendedProperties发现了原因:
1)ExtendedProperties是继承Hashtable的
2)ExtendedProperties自己维护了Keys
{
get { return keysAsListed; }
}
所以,Add方法是Hashtable本身实现的,在使用Add方法增加元素的时候,ExtendedProperties.Keys并没有增加,应该使用扩展出来的AddProperty方法,执行AddProperty才会顺便去维护keysAsListed,我修改初始化的代码后发现一切正常了。后来我回头去看网上的例子,都是使用AddProperty的,汗死!!!最后贴出正确的初始化代码
var props = new ExtendedProperties();
props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");
props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, targetViewFolder);
velocityEngine.Init(props);
不过这回老眼昏花也让我理解了LSP法则,面向对象实践中有一些法则,我往往是只知其然,不知其所以然,最后说说什么是LSP法则。:
LSP: The Liskov substitution principle
子类必须能够替换基类。Subtypes must be substitutable for their base types.
ExtendedProperties继承Hashtable,但是并不能够代替基类,反而会导致行为不正常,让我陷入歧途,一个低级的错误,一个下午的时间,不过总在下班前解决了。