NVelocity实现违反了LSP法则,使我的一个低级错误排查了一个下午。
最近我在做一个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,但是并不能够代替基类,反而会导致行为不正常,让我陷入歧途,一个低级的错误,一个下午的时间,不过总在下班前解决了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架