模板引擎Nvelocity实例

C#

浏览数:228

2019-5-12

前言

最近一直忙于工作,没时间来管理博客,同时电脑也不给力,坏了一阵又一阵,最后还是去给修理了,这不刚一回来迫不及待的就写一篇文章来满足两个月未写博客的紧迫感。

Nvelocity

关于nvelocity就不再过多介绍,这样的文章已经太多太多,我只是将其封装起来用用,其中遇到的问题也会在其中一一进行讲解。为什么会用到该模板引擎是因为要定义不同的格式来进行后续的打印,关于打印后续有时间也和大家讲解讲解,关于打印可以透露一点,有想到过用现成比如园友伍华聪大大介绍的lodop,这款打印还是非常的强大,虽然有免费版,但是也就供学习用,在实际项目中还是要用到比较复杂的打印api,于是乎就得去写了,这个过程幸好有基本的代码供参考,还是学到不少有关打印的知识,无论是在餐厅还是在肯德基等地方都会有打印的小票,之前没怎么去在意过,直到自己遇到要实现这样的打印以及对应的格式在去仔细研究研究,其过程也是受益匪浅。

好,话说了这么多,我们开始进入主题,分割线

实现内容:需要将数据放到xml文件中然后将其反序列化为对象进行后续的传输。。。

如下直接给出封装的Nvelocity。

NVelocityEngine

    public class NVelocityEngine
    {
        private VelocityEngine _velocit;
        private static readonly string templateDir = System.Web.Hosting.HostingEnvironment.MapPath("~/Template");
        public NVelocityEngine(string tempDir)
        {
            //创建NVelocity引擎的实例对象
            this._velocit = new VelocityEngine();
            //初始化该实例对象
            ExtendedProperties props = new ExtendedProperties();

            props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");
            props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");
            props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");

            //设置模板所在目录
            props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, tempDir);
            props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, true);
            props.AddProperty("file.resource.loader.modificationCheckInterval", "30");

            this._velocit.Init(props);
        }

        private static Mutex _Mutex = new Mutex();
        private static NVelocityEngine _MeObj;
        public static NVelocityEngine Create()
        {
            if (_MeObj != null)
                return _MeObj;

            _Mutex.WaitOne();
            if (_MeObj == null)
                _MeObj = new NVelocityEngine(templateDir);
            _Mutex.ReleaseMutex();

            return _MeObj;
        }

        public string GetHtml(IContext context, string templatePath)
        {
            StringWriter writer = new StringWriter();
            Template template = this._velocit.GetTemplate(templatePath, "utf-8");
            template.Merge(context, writer);
            return writer.GetStringBuilder().ToString();
        }
    }
}

NVelocityPage

    public class NVelocityPage
    {

        private IContext _IContext;
        private string _templatePath;

        public NVelocityPage(string templatePath)
        {
            this._IContext = new VelocityContext();
            this._templatePath = templatePath;
        }

        public void Add(string key, object value)
        {
            if (this._IContext.ContainsKey(key))
                this._IContext.Remove(key);
            this._IContext.Put(key, value);
        }

        public string WriteHtml()
        {
            try
            {
                return NVelocityEngine.Create().GetHtml(this._IContext, this._templatePath);
            }
            catch (Exception e)
            {

                throw e;
            }

        }
    }

接下来则是需要反序列化为对象的几个类,命名比较粗糙,将就点看吧。

    [XmlRoot("Table")]
    public class Table
    {
        [XmlArrayItem(typeof(tr), ElementName = "TR")]
        public List<tr> TR { get; set; }
    }

    public class tr
    {
        [XmlArrayItem(typeof(td),ElementName="TD")]
        public List<td> TD { get; set; }
    }

    public class td
    {
        [XmlAttribute("tdValue")]
        public string tdValue { get; set; }
    }

XML文件

<?xml version="1.0" encoding="utf-8" ?>
<Table>
  <TR>
    #foreach($d in $list)
    <tr>
      <TD>
        <td tdValue="$d.Age"/>
      </TD>
    </tr>
    #end
  </TR>
</Table>

测试类:

            var list = new List<Person>()
            {
                new Person(){Age=1,Name="1"},
                new Person(){Age=2,Name="2"},
                new Person(){Age=3,Name="3"},
                new Person(){Age=4,Name="4"}
            };
            var nvelocityPage = new NVelocityPage("table.xml");
            nvelocityPage.Add("list", list);
            var tableXml = nvelocityPage.WriteHtml();
            var memoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(tableXml));
       var xmlSerializer = new XmlSerializer(typeof(Table)); var table = (Table)xmlSerializer.Deserialize(memoryStream);

结果如下:

 反序列为对象时没有正确,估计是在写xml特性有问题结果进行如下修改即可。

将上述

  [XmlArrayItem(typeof(tr), ElementName = "TR")]

修改为如下:

 [XmlArray("TR")]
 [XmlArrayItem("tr")]

同理进行修改则如我们所期望,结果则不再演示。在其过程中在利用内存流进行反序列化时建议进行如下设置

  memoryStream.Position = 0;

之前未进行设置则出现如下错误,后来又未出现,不明白是怎么情况

XML 文档(0, 0)中有错误。缺少根元素

至此,我们利用模板引擎进行数据替换接着进行加载到内存中反序列化为对象就已结束。

总结

之前未接触过将输出的xml数据利用xml特性来进行反序列化为对象,也花了一点时间去看这方面的东西,本以为只能通过加载xml文件来进行反序列化,未曾想到这样也是可以的,多次尝试才最终完成任务,每一次的实际项目应用需要才会使我学习到更多且了解的更透彻。今天写这篇文章脑子也是懵的,终于写完,只是为了两个月未写博客做一个新的开始,后续会陆续讲解项目当中学到的新的知识,希望对阅读本文的你有所启发和帮助,当然文章难免有错误之处、表述不清之处请指出或者错别字,我好及时的修改和完善。

 

作者:Jeffcky