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

作者:且行且思 时间:2022-03-25 02:25:29 

本文实例讲述了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("&lt;img src='{src}' alt='{alt}' /&gt;");
///   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));
///  }
/// }
///
/// 输出为:
/// &lt;img src='pic.bmp' alt='Image' /&gt;
/// &lt;img src='pic.bmp' alt='image' /&gt;
///
/// </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("&lt;img src='{src}' alt='{alt}' /&gt;");
///   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));
///  }
/// }
///
/// 输出为:
/// &lt;img src='pic.bmp' alt='Image' /&gt;
/// &lt;img src='pic.bmp' alt='image' /&gt;
///
/// </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("&lt;img src='{src}' alt='{alt}' /&gt;");
///   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));
///  }
/// }
///
/// 输出为:
/// &lt;img src='pic.bmp' alt='Image' /&gt;
/// &lt;img src='pic.bmp' alt='image' /&gt;
///
/// </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#,动态生成,静态页面
0
投稿

猜你喜欢

  • C# WinForm实现自动更新程序之客户端的示例代码

    2022-03-28 03:26:24
  • 新手Hadoop安装 环境搭建

    2022-12-15 05:34:02
  • 基于request获取访问者真实IP代码示例

    2023-02-15 02:45:13
  • java精度计算代码 java指定精确小数位

    2023-07-31 03:03:58
  • java面向对象之人机猜拳小游戏

    2021-12-20 18:12:34
  • Unity Shader实现序列帧动画效果

    2021-10-31 22:50:18
  • java实现猜拳游戏

    2023-08-04 04:23:52
  • maven的pom文件与打包详解

    2023-12-24 00:23:51
  • c# 基于wpf,开发OFD电子文档阅读器

    2023-09-08 00:10:02
  • Java读取json数据并存入数据库的操作代码

    2023-09-23 06:00:57
  • 各种格式的编码解码工具类分享(hex解码 base64编码)

    2021-11-17 07:04:51
  • Java中Calendar类的一些常用方法小结

    2022-11-21 06:51:06
  • C#中try...catch的使用与常见面试题分享

    2022-10-22 16:30:35
  • Spring Cloud微服务架构的构建:分布式配置中心(加密解密功能)

    2021-10-24 05:49:59
  • Java详细讲解堆排序与时间复杂度的概念

    2023-10-20 02:00:11
  • Java中的接口回调实例

    2023-11-29 08:05:43
  • C#中使用强制类型实现字符串和ASCII码之间的转换

    2022-05-15 14:57:48
  • Hibernate实现悲观锁和乐观锁代码介绍

    2022-04-25 09:43:45
  • Java 常见的几种内存溢出异常的原因及解决

    2023-02-21 16:44:50
  • flutter实现扫码枪获取数据源禁止系统键盘弹窗示例详解

    2023-07-23 01:52:41
  • asp之家 软件编程 m.aspxhome.com