欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#实现动态生成静态页面的类详解

程序员文章站 2022-06-09 08:19:35
本文实例讲述了c#实现动态生成静态页面的类。分享给大家供大家参考,具体如下: 动态生成静态页面有许多好处,比如生成html网页有利于被搜索引擎收录。同时,由于减少了数据访...

本文实例讲述了c#实现动态生成静态页面的类。分享给大家供大家参考,具体如下:

动态生成静态页面有许多好处,比如生成html网页有利于被搜索引擎收录。同时,由于减少了数据访问,减轻对数据库访问的压力,提高了网页打开速度。

基本思路:

使用一个字符串作为页面模板,再页面中包含用若干标志(用 {标志名} 表示),生成页面时,将标志替换为对应的值。

实现方法:

在初始化texttemplate实例时读入模板,以标志为分割点将模板分割成几部分,生成页面时只需简单的将模板内容和标志的值连接起来。例如:
假如有一个模板 abcd{tag1}efg{tag2}hij{tag3}kmun
初始化时将模板分割成 "abcd","efg","hij","kmun"四个字符串,
假设tag1=“123”,tag2=“456”,tag3=“789”
则生成是相当于执行"abcd"+"123"+"efg"+"456"+"hij"+"789"+"kmun"

代码:

using system;
using system.collections.generic;
using system.text;
using system.text.regularexpressions;
using system.collections;
using system.io;
/// <summary>
/// 表示一个文本模板,该类使用一个字符串作为模板,通过将模板中的标志替换为对应的值(模板中的标志用 {标志名} 表示)生成新的文本
/// </summary>
/// <example>以下代码用文本模板生成img标志
/// <code>
/// static class program
/// {
///  [stathread]
///  static void main()
///  {
///   texttemplate temp = new texttemplate("<img src='{src}' alt='{alt}' />");
///   console.writeline(temp.render("pic.bmp","image"));
///   hashtable values = new hashtable();
///   values.add("src", "pic.bmp");
///   values.add("alt", "image");
///   console.writeline(temp.render(values));
///  }
/// }
///
/// 输出为:
/// <img src='pic.bmp' alt='image' />
/// <img src='pic.bmp' alt='image' />
///
/// </code>
/// </example>
public class texttemplate
{
 texttemplatetag[] _tags;
 string[] _contentparts;
 int _tagcount;
 private texttemplate()
 {
  _tagcount = 0;
  _tags = null;
  _contentparts = null;
 }
 /// <summary>
 /// 用指定的模板初始化texttemplate
 /// </summary>
 /// <param name="content">模板内容</param>
 public texttemplate(string content)
 {
  fromstring(content);
 }
 /// <summary>
 /// 用指定的模板初始化texttemplate,模板内容重文件读入
 /// </summary>
 /// <param name="file">模板文件位置</param>
 /// <param name="encoding">文件使用的编码</param>
 public texttemplate(string file, encoding encoding)
 {
  streamreader sr = new streamreader(file, encoding);
  try
  {
   string content = sr.readtoend();
   fromstring(content);
  }
  catch (exception)
  {
   sr.close();
   throw;
  }
  sr.close();
 }
 /// <summary>
 /// 读入模板并以标志为分割点分割模板
 /// </summary>
 /// <param name="content"></param>
 private void fromstring(string content)
 {
  matchcollection mc = regex.matches(content, "{\\w+}");
  _tagcount = mc.count;
  _tags = new texttemplatetag[mc.count];
  _contentparts = new string[mc.count + 1];
  int index = 0;
  foreach (match m in mc)
  {
   _tags[index++] = new texttemplatetag(m.value.substring(1, m.value.length - 2), m.index, m.length);
  }
  int start = 0;
  index = 0;
  foreach (texttemplatetag con in _tags)
  {
   _contentparts[index] = content.substring(start, con.position - start);
   start = con.position + con.length;
   index++;
  }
  if (start < content.length) _contentparts[index] = content.substring(start);
 }
 /// <summary>
 /// 用指定的值生成文本
 /// </summary>
 /// <param name="values">各标志对应的值(用标志名作为key)</param>
 /// <returns>生成的文本</returns>
 /// <example>以下代码用文本模板生成img标志
 /// <code>
 /// static class program
 /// {
 ///  [stathread]
 ///  static void main()
 ///  {
 ///   texttemplate temp = new texttemplate("<img src='{src}' alt='{alt}' />");
 ///   console.writeline(temp.render("pic.bmp","image"));
 ///   hashtable values = new hashtable();
 ///   values.add("src", "pic.bmp");
 ///   values.add("alt", "image");
 ///   console.writeline(temp.render(values));
 ///  }
 /// }
 ///
 /// 输出为:
 /// <img src='pic.bmp' alt='image' />
 /// <img src='pic.bmp' alt='image' />
 ///
 /// </code>
 /// </example>
 public string render(hashtable values)
 {
  stringbuilder result = new stringbuilder(8 * 1024);
  int i = 0;
  for (i = 0; i < _tagcount; i++)
  {
   result.append(_contentparts[i]);
   if (values[_tags[i].name] != null)
    result.append(values[_tags[i].name]);
   else
    result.append("{" + _tags[i].name + "}");
  }
  result.append(_contentparts[i]);
  return result.tostring();
 }
 /// <summary>
 /// 用指定的值生成文本
 /// </summary>
 /// <param name="args">各标志对应的值(忽略标志名,第一个标志对应第一个参数,以此类推)</param>
 /// <returns>生成的文本</returns>
 /// <example>以下代码用文本模板生成img标志
 /// <code>
 /// static class program
 /// {
 ///  [stathread]
 ///  static void main()
 ///  {
 ///   texttemplate temp = new texttemplate("<img src='{src}' alt='{alt}' />");
 ///   console.writeline(temp.render("pic.bmp","image"));
 ///   hashtable values = new hashtable();
 ///   values.add("src", "pic.bmp");
 ///   values.add("alt", "image");
 ///   console.writeline(temp.render(values));
 ///  }
 /// }
 ///
 /// 输出为:
 /// <img src='pic.bmp' alt='image' />
 /// <img src='pic.bmp' alt='image' />
 ///
 /// </code>
 /// </example>
 public string render(params object[] args)
 {
  stringbuilder result = new stringbuilder(2 * 1024);
  int i = 0;
  for (i = 0; i < _tagcount; i++)
  {
   result.append(_contentparts[i]);
   result.append(args[i].tostring());
  }
  result.append(_contentparts[i]);
  return result.tostring();
 }
 /// <summary>
 /// 用指定的值生成文本,并保存到文件中
 /// </summary>
 /// <param name="file">要保存的文件路径</param>
 /// <param name="encoding">文件的编码</param>
 /// <param name="values">各标志对应的值(用标志名作为key)</param>
 public void saveas(string file, encoding encoding, hashtable values)
 {
  streamwriter sw = new streamwriter(file, false, encoding);
  try
  {
   string content = render(values);
   sw.write(content);
  }
  catch (exception)
  {
   sw.close();
   throw;
  }
  sw.close();
 }
 /// <summary>
 /// 用指定的值生成文本,并保存到文件中
 /// </summary>
 /// <param name="file">要保存的文件路径</param>
 /// <param name="encoding">文件的编码</param>
 /// <param name="args">各标志对应的值(忽略标志名,第一个标志对应第一个参数,以此类推)</param>
 public void saveas(string file, encoding encoding, params object[] args)
 {
  streamwriter sw = new streamwriter(file, false, encoding);
  try
  {
   string content = render(args);
   sw.write(content);
  }
  catch (exception)
  {
   sw.close();
   throw;
  }
  sw.close();
 }
 /// <summary>
 /// 将模板以指定的分隔标志分隔成小模板
 /// </summary>
 /// <param name="splittag"></param>
 /// <returns></returns>
 public texttemplate[] split(string splittag)
 {
  list<texttemplate> temps = new list<texttemplate>();
  list<string> contentparts = new list<string>();
  list<texttemplatetag> tags = new list<texttemplatetag>();
  int i = 0;
  foreach (string content in _contentparts)
  {
   contentparts.add(content);
   if (i >= _tags.length || _tags[i].name == splittag)
   {
    texttemplate newtemp = new texttemplate();
    newtemp._contentparts = contentparts.toarray();
    newtemp._tags = tags.toarray();
    newtemp._tagcount = tags.count;
    temps.add(newtemp);
    contentparts.clear();
    tags.clear();
   }
   else
    tags.add(new texttemplatetag(_tags[i].name, _tags[i].position, _tags[i].length));
   i++;
  }
  return temps.toarray();
 }
}
internal class texttemplatetag
{
 int _position, _length;
 string _name;
 public texttemplatetag(string name, int pos, int len)
 {
  _name = name;
  _position = pos;
  _length = len;
 }
 public string name
 {
  get { return _name; }
 }
 public int position
 {
  get { return _position; }
 }
 public int length
 {
  get { return _length; }
 }
}

实例代码:

static class program
{
 [stathread]
 static void main()
 {
  texttemplate temp = new texttemplate("<img src='{src}' alt='{alt}' />");
  console.writeline(temp.render("pic.bmp","image"));
  hashtable values = new hashtable();
  values.add("src", "pic.bmp");
  values.add("alt", "image");
  console.writeline(temp.render(values));
 }
}

输出为:

<img src='pic.bmp' alt='image' />
<img src='pic.bmp' alt='image' />

其他应用:

texttemplate还可以用来在安装网站时生成web.config文件,只需定义以下模板:

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.netconfiguration/v2.0">
 <appsettings></appsettings>
 <connectionstrings>
  <add
   name="djdb.localsqlserver"
   connectionstring="{connectionstring}"
   providername="system.data.sqlclient"
  />
 </connectionstrings>
 其他配置
</configuration>

在设置标志 connectionstring 的值即可,这种方法比用xmldocument类要方便得多。

总结:

texttemplate的优点有:

1、模板只在初始化时就分析并分割存储,当使用同一模板生成多个页面时,只是简单的件模板内容和标志的值连接起来,不需要每次都去分析模板,如果使用string的replace方法则每一次都要去分析字符串,而且如果标志值中含有标志,会影响生成的页面。

2、模板可以从文件读入,因此模板文件可以使用各种网页制作工具编辑。

更多关于c#相关内容感兴趣的读者可查看本站专题:《c#数据结构与算法教程》、《c#常见控件用法教程》、《c#面向对象程序设计入门教程》及《c#程序设计之线程使用技巧总结

希望本文所述对大家c#程序设计有所帮助。