因为另有开发记录工具最新没怎么在 cnblog 写开发备忘.不过我觉得这个是个比较严重的问题,觉得有必要让更多的人知道处理方法,所以在 cnblog 也放上一篇希望广为传播.
因为现在网络上vs2008能直接使用的版本很难找,所以放一个修改自 sourceforge 能用的版本,并且说明修改的方式.
--------------------------------------------------
第一次修改
--------------------------------------------------
NVelocity 这个工具的使用相信大多数网友都是因为和我一样在 java 时使用的是 Velocity ,因此在使用 C# 特别希望有一个类似的工具包.而搜索得到的就是 NVelocity.
NVelocity 两三年前我是用过的,所以并不觉得这次用会有什么问题. 照例在网上搜索后加入工程及网上的各种示例就点运行.为料出现了 "It appears that no class was specified as the ResourceManager..." ,心里也并不慌张,因为根据经验估计也就是某个 dll 引用没弄进来. 结果折腾了各种文件和网上的各种例子就是不对. 不知不觉一个上午就过去了,觉得事情有点严重,放下大意的心情,打开了我以前的工程.发现有几个不同的地方:
1.之前公司用的是 vs2010 , 现在用的是 vs2008,没办法直接编译.
2.之前工程中只有一个 NVelocity.dll 文件,也没有源码,而这次下载的却有 NVelocity.dll,NVelocity.http.dll 及源码等多个文件.
好吧,我把这个 NVelocity.dll 替换好了.但编译时即报错,查看了文件的版本信息,其写明了是 for .net 4.0 的,当然这时直接换用 vs2010 就好了.不过我的情况稍微特殊,生产环境是 .net 2.0 的,不是太方便让人升级,再说升级 .net 环境有时候会成为灾难 -- 我以前升级 .net 3.5 时碰到过很多次,虽然 .net 4.0 好很多.实在不想节外生枝.
好吧,又在网上搜索了无数的类似问题.都不行.期间看到说因为 NVelocity 交由了什么 xxx 维护了,所以 NVelocity 的源码版本有多个. 这时意外在某网友的例子中发现了能用的 .net 2.0 版本 NVelocity.dll 但其文件没有版本信息,显然不是官方的,但这位网友的文章显示是多次转载已经找不到其如何修改的信息了.我下载的文件位于(NVelocity-0.4.2.8580):
http://nvelocity.sourceforge.net/
因为这是 google 搜索的第一个,而 baidu 搜索的第一个就是那个 for .net 4.0 版本的:
http://nvelocity.codeplex.com/
而网友那个可用的 .net 2.0 版本已经没有下载地址了.说实话我理解不了 sourceforge.net 这个为什么用不了,这么有名的控件在这么有名的网站上提供的文件居然是错误的.通过我搜索的其他信息,相应的 bug 应当是有人提交了的,不知为什么没有提交到 sourceforge.net 这里.
好了,不管那么多,至少在我的中文版本 vs2008 上需要修改以下部分才能正常使用:
文件 ResourceLocator.cs 中
try
{//clq
foreach (Assembly a in assemblies)
{
String prefix = a.FullName.Substring(0, a.FullName.IndexOf(",")).ToLower();
String[] names = a.GetManifestResourceNames();
try
{//clq //这里都没错,应当是前面的两句话造成的
foreach (String s in names)
{
if (s.ToLower().Equals(fn) || s.ToLower().Equals(prefix + "." + fn))
{
this.filename = s;
assembly = a;
isResource = true;
}
}
}
catch (System.Exception ex)
{
String s = ex.Message;
System.Console.WriteLine("bbbbbb:" + s);
}//clq
}
}catch(System.Exception ex)
{
String s = ex.Message;
System.Console.WriteLine("aaaaaa:" + s);
}//clq
}//if clq
根据我的测试大概的出错原因是,某个资源文件在反射机制搜索时不支持某个接口,导致其异常退出了剩余资源的处理.所以直接加几个 try 就行了(ps:反射实现,恐怕效率不高吧).
这样修正后下面这样的代码就可以通过运行了.
VelocityEngine vltEngine = new VelocityEngine();
//4.0 这里是 RuntimeConstants.RESOURCE_LOADER
vltEngine.SetProperty(RuntimeConstants_Fields.RESOURCE_LOADER, "file");
string path = _this.Server.MapPath("~/");
vltEngine.SetProperty(RuntimeConstants_Fields.FILE_RESOURCE_LOADER_PATH, path);
vltEngine.Init();//不修改库代码,这里会报错
--------------------------------------------------
第二处修改
--------------------------------------------------
以上修改后使用一段时间后,因为我个人的工具链中很多是不支持 utf8 的(或者很麻烦),在此将模板改为了普通的 gbk 编码方式.这时发现这个版本没法纠正编码形式.我修改了一个地方才行.正常的编码纠正代码为:
vltEngine.SetProperty(RuntimeConstants_Fields.OUTPUT_ENCODING, "GB2312");//修改 NVelocity-0.4.2.8580 的源码后才能用这两个,并且最好是用 GBK
vltEngine.SetProperty(RuntimeConstants_Fields.INPUT_ENCODING, "GB2312");//
在此版本 nvelocity 中不起作用,需要修改:
Template.cs 文件中
//System.IO.StreamReader br = new System.IO.StreamReader(new System.IO.StreamReader(is_Renamed, System.Text.Encoding.GetEncoding(encoding)).BaseStream);
System.IO.StreamReader br = new System.IO.StreamReader(new System.IO.StreamReader(is_Renamed, System.Text.Encoding.GetEncoding(encoding)).BaseStream, System.Text.Encoding.GetEncoding(encoding));//clq 2014.05.23
很显然作者可能是老外,编码指定的位置弄错了.
--------------------------------------------------
为方便大家参考,我放上修改后的全部项目文件,这里用的是 debug 版本,对效率有要求的环境请自动编译其他版本.代码修改的地方不多,大家可全文搜索 "//clq" 字样就能找到,其他代码因为本人水平有限也看不懂也不敢乱改.出于稳定和不想惹麻烦的原因未来也不打算大改,能在我目前这个小项目中用就行.
下载地址为:
https://files.cnblogs.com/-clq/NVelocity-0.4.2.8580%5B2014.05.23%5D%5Bclq_modify%5D.zip
--------------------------------------------------
如果还有其他 bug 我会再上传新版本.另外也希望有了解内情的网友介绍下 nvelocity 如此混乱的原因.