2008年8月10日
#
2008年1月24日
#
这个类库的作用是帮助程序员快速,自由的生成html页面。原先以为他可以算是一个简易模板引擎。但是现在仔细考虑了一下,觉得他还算不上是引擎。只能算是一个辅助类库。07年9月,兼职工作停止后,就没有在用过。前一段时间研究异步编程,顺便类库也加上了可以异步执行的功能。内部的一些算法也做了优化和更支持并发处理的调整。
主要有两个改变,一个是可以用{$静态包含文件:Include(/Include/Bottom.htm)$}这样的参数形式。直接包含静态文件内容做参数。 还可以通过{$动态包含文件:Exec(/Include/Exec.htm)$} 这样的参数形式,包含其他模板页,得到解析结果作为参数。
在page_load执行完毕后。所有有异步标志的标签{$异步显示表格:12:20::异步$}会开始异步执行。如果页面要连接多个数库。这个功能会有用处。
并且里面有我以前兼职项目的模板和处理类代码。可以看下习惯用法。Demo是昨天写的发给四个邮件联系的程序员的。今天修改了一下,现在也传到这里,希望看了以后,对其他程序员的思想提高有些帮助。
地址: http://files.cnblogs.com/vitality2007/ShowDemo.rar
Logic 项目的ShowTest.cs 的 210 行象下有点错误,导致异步翻页出错。刚发现,下载文件内已经修改了。
2007年7月20日
#
最近使用微软企业库,在做分页绑定的时候发现好象还没有多少通用的方法.为了灵活和换数据库,我不能使用存储过程.为了开发速度最快.我就是用datagrid绑定了.
以前长用的 DataAdapter.Fill(ds, StartRecordNo, PageSize, TableName); 这样获取某一页的数据.但是用微软企业库总么获得这样的数据按 .网上介绍 Database 类的 GetDataAdapter() 函数的文章太少了. 不过最终做成通用分页函数了.
用一条sql语句 select * from AAA 这样的语句,不是分页sql语句.得到总数目,总页数
现在定义的数据访问接口
public interface ISysMangerProvider
{
//执行sql语句获得DataSet数据
DataSet GetDataSetBySqlcomm(string Sqlcomm);
//执行sql语句获得DataSet数据 ,提供分页
DataSet GetDataSetBySqlcomm(int StartRecordNo, int PageSize, string Sqlcomm,string TableName);
//执行sql语句返回影响的行数目
int ExecSqlcomm(string Sqlcomm);
}
我门在微软企业库外面在包一层,放一些可以通用的函数 ,也可以简化数据提供者类的构造,和减少代码膨胀
#region 数据提供者,通用基础类
/// <summary>
/// 数据提供者,通用基础类
/// </summary>
public abstract class DataProviderBaseClass
{
#region 定义变量
protected Database db;
//protected object ReturnObjectValue;
#endregion
#region 构造函数
protected DataProviderBaseClass()
{
}
protected DataProviderBaseClass(int i): this()
{
db = DatabaseFactory.CreateDatabase();
}
protected DataProviderBaseClass(string connectionName): this()
{
db = DatabaseFactory.CreateDatabase(connectionName);
}
protected DataProviderBaseClass(SelectDataBae SDB):this()
{
db = DatabaseFactory.CreateDatabase(PublicNews.ChangeDataBase(SDB));
}
#endregion
#region 执行sql语句得到DataSet类型数据
/// <summary>
/// 执行sql语句得到DataSet类型数据
/// </summary>
/// <param name="Sqlcomm"></param>
/// <returns></returns>
protected DataSet ExecuteDataSetBySqlcomm(string Sqlcomm)
{
DataSet ds;
using (DbConnection dbConnection = this.db.CreateConnection())
{
ds = this.db.ExecuteDataSet(CommandType.Text, Sqlcomm);
dbConnection.Close();
}
return ds;
}
#endregion
#region 执行sql语句获得DataSet数据 ,提供分页
/// <summary>
/// 执行sql语句获得DataSet数据 ,提供分页
/// </summary>
/// <param name="PageNo">当前行数</param>
/// <param name="PageSize">一页分页数量</param>
/// <param name="Sqlcomm">sql语句</param>
/// <returns>DataSet对象</returns>
protected DataSet ExecuteDataSetBySqlcomm(int StartRecordNo, int PageSize, string Sqlcomm, string TableName)
{
DataSet ds = new DataSet();
using (DbConnection dbConnection = this.db.CreateConnection())
{
DbCommand dbCommand = this.db.GetSqlStringCommand(Sqlcomm + " ; select @@Rowcount ; ");
DbDataAdapter dbDataAdapter = this.db.GetDataAdapter();
dbCommand.Connection = dbConnection;
dbDataAdapter.SelectCommand = dbCommand;
dbConnection.Open();
dbDataAdapter.Fill(ds, StartRecordNo, PageSize, TableName);
dbConnection.Close();
}
return ds;
}
#endregion
#region 执行sql语句返回影响的行数目
/// <summary>
/// 执行sql语句返回影响的行数目
/// </summary>
/// <param name="stringcomm"></param>
/// <returns></returns>
protected int ExecIntBySqlcomm(string Sqlcomm)
{
using (DbConnection dbConnection = this.db.CreateConnection())
{
dbConnection.Open();
int i = this.db.ExecuteNonQuery(CommandType.Text, Sqlcomm);
dbConnection.Close();
return i;
}
}
#endregion
#region 检测DataSet对象是否有数据
/// <summary>
/// 检测DataSet对象是否有数据
/// </summary>
/// <param name="Ds">要检测的对象</param>
/// <returns>返回结果</returns>
public static bool CheckDataSet(DataSet Ds)
{
try
{
if (Ds != null && Ds.Tables.Count > 0 && Ds.Tables[0].Rows.Count > 0)
{
return true;
}
else
{
return false;
}
}
catch
{
throw;
}
}
#endregion
#region 检测DataSet对象是否有数据,分页支持
/// <summary>
/// 检测DataSet对象是否有数据,分页支持
/// </summary>
/// <param name="Ds">要检测的对象</param>
/// <returns>返回结果</returns>
public static bool CheckDataSetForPage(DataSet Ds, ref int ResultCount)
{
try
{
if (Ds != null && Ds.Tables.Count > 0 && Ds.Tables.Count == 2 && Ds.Tables[0].Rows.Count > 0)
{
ResultCount = Convert.ToInt32(Ds.Tables[1].Rows[0][0]);
if (ResultCount == 0)
{
return false;
}
else
{
return true;
}
}
else
{
return false;
}
}
catch
{
throw;
}
}
#endregion
}
#endregion
好了 最后数据提供者类就很简单了.
public class SysMangerProvider : DataProviderBaseClass ,ISysMangerProvider
{
#region 构造函数
public SysMangerProvider():base(1)
{
}
public SysMangerProvider(string connectionName):base(connectionName)
{
}
public SysMangerProvider(SelectDataBae SDB): base(SDB)
{
}
#endregion
#region 执行sql语句得到DataSet类型数据
/// <summary>
/// 执行sql语句得到DataSet类型数据
/// </summary>
/// <param name="Sqlcomm"></param>
/// <returns></returns>
public DataSet GetDataSetBySqlcomm(string Sqlcomm)
{
return base.ExecuteDataSetBySqlcomm(Sqlcomm);
}
#endregion
#region 执行sql语句获得DataSet数据 ,提供分页
/// <summary>
/// 执行sql语句获得DataSet数据 ,提供分页
/// </summary>
/// <param name="PageNo">当前行数</param>
/// <param name="PageSize">一页分页数量</param>
/// <param name="Sqlcomm">sql语句</param>
/// <returns>DataSet对象</returns>
public DataSet GetDataSetBySqlcomm(int StartRecordNo, int PageSize, string Sqlcomm,string TableName)
{
return base.ExecuteDataSetBySqlcomm(StartRecordNo, PageSize, Sqlcomm, TableName);
}
#endregion
#region 执行sql语句返回影响的行数目
/// <summary>
/// 执行sql语句返回影响的行数目
/// </summary>
/// <param name="stringcomm"></param>
/// <returns></returns>
public int ExecSqlcomm(string Sqlcomm)
{
return base.ExecIntBySqlcomm(Sqlcomm);
}
#endregion
}
在前台绑定的时候就非常简单了
int ResultCount = 0;
this.ds = this.SM.GetDataSetBySqlcomm(startIndex, this.DataGrid1.PageSize, " select * from PageInfo " ,"ShowList" );
if (DataProviderBaseClass.CheckDataSetForPage(this.ds, ref ResultCount))
{
this.DataGrid1.VirtualItemCount = ResultCount;
this.DataGrid1.DataSource = this.ds.Tables[0];
this.DataGrid1.DataBind();
}
else
{
this.Response.Write("对不起,没有获取到数据。");
}
好了 解决用微软企业库的sql语句分页问题.
2007年5月10日
#
站点可以看
http://210.51.166.37:81/ 下载代码在
/Files/vitality2007/WebSite_Demo_Down.rar加上了对包含动态页,包含静态页的支持, 完全虚拟路径加?加参数 和 虚拟路径上无参数在路径内直接提取参数两种地址重写.
2007年3月1日
#
摘要: 使用模板在php和java里很普及。微软官方没有给我门提供类似php模板的工具类。应为aspx页面本身就是模板。控件也是模板,并且微软官方提供的接口之丰富,功能支持之多使他们没有必要在提供类似php模板之类的工具类库。 标准的aspx页面也是可以实现MVC的。但是有的时候会觉得MVC功能实现的不是很彻底。比如一个程序员和一个美工结合。可以对页面进行逻辑和外观上的改版。但是一个美工自己是只能修改外观...
阅读全文
2006年11月1日
#
摘要: 在很多时候。我门需要一种页面。这种页面不需要回送。为了速度。不需要使用服务器控件。必须保持高响应。他只要做动态显示。有不能做成静态页面。比如一些vip的文章显示。投票查看了。 webform框价功能强大。但是看看一个system.web.ui.page的源码。[ToolboxItem(false),DesignerSerializer("Microsoft.VisualStudio.Web.Web...
阅读全文
2006年8月27日
#
最近新公司的工作主要是做静态页面,写策划。还有就是学习CommunityServer项目。加起来做这些已经一个月了。周六去了上地七街一家公司。和人家谈了谈,发现这个模板类已经放了好长时间了。回来后觉得应该补上模板类一直需要的一个功能了。就是支持信息载体类。就是说在自定义的标签解析函数内,我门可以获取外界传近来的自己定义的各种各样的信息载体类内的数据。加上信息载体类后,用模板类,也可以说用模板引擎来开发页面才更有实用意义。
在用简易模板引擎开发的哪个blog项目中(www.93913.com)。应为标签分析接口是可以随意扩展的。所以可以很自然的把各种各样的信息载体类传到模板引擎内。但是在这个模板类中,底层类已经固定了。原先是为了减少对象的资源消耗。不得不把所有类做成sealed class 。加上当时基本不考虑使用减少效率的强制类型转换。这样就为实现这个功能设置了一个很难通过的技术点。昨天晚上我对原来的结构做了一次大修改。把底层类改为抽象类。使用了一点强制类型转化。修改了委托对象的缓存。这样就解决了在标签解析函数内直接引用外界信息载体类的问题。
先说一下用模板引擎开发的想法,也许还有很多错误,拿出来大家批批。
在看见一个页面的时候。我门把里面的页面布局和动态部分切出来。放到一个文件内,这个文件就是我门的模板文件了。在把文件内的动态部分切出来。把动态部分的位置上先放上一个标签(什么是标签,总么使用,去我的blog上 vitality2007.cnblogs.com 看)。在标签解析类内在加上一个和标签对应的标签解析函数。
这样我门可以说是暂时实现了页面布局和页面功能的分离。布局由模板文件内的html代码决定。功能由模板文件内的标签决定。(当然标签解析后输出的不可能是完全的数据。这个其实可以做到。但是会产生过多的标签,一般不采用。标签转换后输出的大部分是数据和html的混合字符串。我门可以把样式,参数当作标签参数传进去来控制标签解析输出部分的布局和内容了)
功能独立了发现了一个问题。他和页面的联系程度减少了。数据信息必须要通过模板类的属性才可以传到标签解析函数内。为了减少属性的数量和灵活性。很自然的写出了一种大量的类。他们有很多的属性,类对象就是为了保留数据而生成的。这样的类对象,我就把他叫做信息载体类。
现在流程就很清晰了。页面的布局已经提取出来放到了模板文件内了。页面的功能已经全部提取出来并写好对应的函数放在了逻辑层的标签解析类内了。
1 我门先在UI层的页面上获取到我门想要的一切参数。通过逻辑层传到了数据层。
2 数据层产生了对应请求的信息载体类对象。里面包含什么信息你自己定义,一般
写成sealed class ,并实现垃圾回收接口。方便析构。
3 信息载体类传到了逻辑层,并和模板文件路径信息一起传到了模板引擎内。
4 在标签解析函数上,通过获取信息载体类的数据,和传近来的其他数据。实现身份判断了,数据处理了。显示排版了,所有的逻辑处理全在这实现。
5 标签解析的数据在返回模板引擎内和模板文件合并。合并的数据在传到UI层在页面上显示出来。
对应的ajax处理过程也差不多。这样一个站点的所有页面全部是由模板引擎来生成的。布局 功能 数据 三方面实现了一定的分离。并且多使用缓存。尽量提升速度。站点维护 修改的时候方便一些。
将会有小于0.5%的概率在生成页面上显示一些模板引擎的来源信息,但信息只能显示在非loop循环外的第一个自定义解析标签后。信息表示格式如下。在代码中以写死。
"<span style='display:none;width:0px;height:0px;'><a href='http://vitality2007.cnblogs.com' title='asp.net开发模板引擎' >asp.net开发模板引擎</a></span>"
加起来模板引擎来源信息的显示不会超过0.25%
例子没有时间新做。我只做了最简单的例子,这次也只做了必要的修改。建立一个名叫TemplateWeb的虚拟目录就可以了。
以后有时间我会新做一个示例的。
下载地址 /Files/vitality2007/TemplateWeb.rar
2006年6月24日
#
下载 /Files/vitality2007/TemplateWeb.rar
不管用什么样的服务器端技术。客户端接受的都是html字符串。在接受的项目中,于是我就使用了一种比较极端的方式。完全抛弃服务器端控件。自己写函数一个table一个td的拼出最终显示页。有点类似与以前asp的开发方式。不使用服务器端控件。可以加快页面生成速度,节省了服务器资源。连微软都提倡尽量避免使用服务器端控件。用ajax实现服务器端控件的回送,可以得到更好的用户体验。
为了方便开发,于是借用php模板类的一些思路。开发出一个完全适合asp.net的模板类。模板类作的就是辅助你完成最终的页面html字符串拼接。程序员只要完成关键的逻辑。数据处理。烦琐的html字符串拼接,合成全部是由模板类来完成。标签不只是和一个字段结合。使用net里的委托。方便的和一个函数调用结合。既增加了标签输出结果的灵活性。有完全避免了使用反射带来的性能损耗。个人觉得,开发asp.net的模板类,是应该要使用委托的。
直接修改模板内标签的参数,控制命令。可以在不重新编译的情况下。动态控制页面程序的编译后输出结果。带来的结果是网站修改页面时,原先很多必须要重新修改代码,重新编译后才可以实现的结果,现在只要维护人员改改标签参数,就可以实现。当然要增加功能,必须要加新的标签了。用w3c的思想。把样式类的名字做为标签的参数数值,直接把样式传到标签解析函数内,生成解析结果。可以做到只改变标签参数,使用不同的样式。就可以让相同的页面有两种截然不同的表现形式。改版太方便了。
在得到美工的静态页面以后。一般使用模板类的做法是首先页面把可以分离出来的部分切出来。做成专门的页面模板碎片。程序员在把模板碎片内的表示数据逻辑的部分用一个标签代替。写出对应的标签解析函数。当模板类解析碎片完毕以后得到的解析结果可以写到shtml文件内,让动态或静态页包含。也可以直接在动态页上输出解析结果。当然还可以直接写到一个静态页上。更新静态页。甚至我门可以让用户自己修改模板碎片,用户自己定植页面显示方式。
我的例子是读模板产生一个新的静态页或直接显示,但是模板类内部的算法表示,他更大的作用是读模板碎片。并把解析的字符串直接在动态页上显示。
我个人比较懒,也没有很多时间。除了对模板类做一些性能优化以外。使用方法的例子几乎没有更新过。大家就看 这个地址的站点 www.93913.com 这个站点完全使用模板类一个表一个表的拼出来的,绝大部分页面。都是有对应的模板页的。其中的blog部分,完全是模板来实现的。熟练使用模板类,开发这种拼页面的项目。开发速度一点也不比用控件慢。并且这个站点是用一种正则模板类来开发的。除了标签的使用方法一样。不支持命令块部分,不支持loop循环。不缓存模板和一些分析数据。个人测试,正则模板类标签定位速度比指针模板类定位速度要慢上9倍以上。这个站点说明,用模板开发,完全拼页面输出的站点是可行的。
介绍:
此模板类是为三层架构大型web站点开发而编写的。StringTempletReplet.dll组件内包含模板类。
StringTempletReplet命名空间内的模板类可以使用在UI层,也可以使用在逻辑层。
************************************************************************************************
运行方法:
建立一个名叫 TemplateWeb 的虚拟目录指象 TemplateWeb 文件夹
运行内部的 Default.aspx 页面。在页面cs文件上有对应说明。
第一次打开页面应为要保留委托对象和模板文件,标签解析数据到缓存中,所以真正的速度要看第一 次以后的。当然现在的开发趋势是尽量使用内存内的数据,应为现在的服务器的内存一般都很大。瓶 径多发生在和数据库的连接上,很少是内存的使用上。当然如果你的服务器内存小,可以尽量使用小 的模板页面。
************************************************************************************************
原理介绍:
一种标签替换的模板。使用了c#中的指针运算查找标签位置。
用委托对象指象标签对应的解析函数,并用静态对象缓存全部委托对象。
在不改变模板正文的情况下,缓存全部模板内容。缓存模板解析数据。改变配置,可以动态更换模板
也可以非动态更换模板。达到更快的速度。
************************************************************************************************
标签介绍:
在成对特殊符号{$ 和 $} 之间的内容为标签
如
{$标签名:参数1:参数2:参数3::字符10$}
{$标签名:参数1:参数2::字节10$}
在标签内部通过 :: 符号把标签分为 标签参数部分 和 命令控制部分 两块
{$标签名:参数1:参数2:参数3::字节10$}
标签参数部分 :: 命令控制部分
在这两部分内以:号分割标签参数部分和命令控制部分
标签参数部分: 第一个为标签名,就是标签解析函数的对应名称,以后的为函数的参数, 标签解析函数接受全部参数类型为string类型的,参数个数为0--20个的函数,返回类 型为string类型
命令控制部分: 现在只有两个命令符号 字符 和 字节 ,后带一个数字参数,表示截取标签解析结果 的长度。我以后会在扩展其他的命令控制符号
标签和函数对应请看Business.cs 文件内说明
标签具体使用规则请看templet/aa1.htm 模板内说明
具体调用规则请看项目中的这三个aspx页面
WriteArticon.aspx : 读模板 解析 写入文件 用于产生静态页面的新闻系统
ReturnText.aspx : 读模板 解析 返回字符串 用与写经常要改变外观的动态页面,换皮肤的页 面。
************************************************************************************************
标签动态取值:
标签解析函数除可以接受标签内传来的固定参数数值外。可以有三种方式接受动态参数
象模板类传递 Datatable 和 Hashtable 对象以后
(Datatable 从数据层获取 ,Hashtable 一般是页面内变量集合和其他要传近来的变量)
1。 dt[5][name] : 表示取Datatable内5行name列上的数值,第一个为数字,第二个是列名
2。 dt[name] : 在loop循环外表示取Datatable内0行name列上的数值,一个参数表示列名
在loop循环内表示取Datatable内name列上的数值,取那些行通过loop标签的参 数决定
3。 page[PageId] :表示取Hashtable对象内PageId键上的数值,返回string类型
如 {$二个参数书签:dt[3][word]:page[UserId]::字符10$}
{$dt[5][name]$} {$dt[name]$} {$page[PageId]$} 或
{$dt[5][name]::字符10$} {$dt[name]::字符10$} {$page[PageId]::字符10$}
这样的标签表示直接在页面上显示对象内的数值
************************************************************************************************
页面或类内调用模板类方法:
可在页面或类内调用
产生对象,关联对应标签函数解析类
//Templet/aa1.htm 模板内标签的解析函数在Business.cs类内 。
//那么我门只要让Business.cs 类继承 FunctionList 类
//在这里我门只要在这一行后面 new Business() 一个Business类对象就可以了
//用接口实现多态,代码看起来有点麻烦。 自己用的时候只要修改最后一个"new Business()" 为自 //己的包含标签解析函数的类对象就可以了
ILabelAnalyStart objILabel=(ILabelAnalyStart) new TempletReplet(new Business());
//读模板路径属性
objILabel.ReadFilePath=this.Server.MapPath("templet/aa1.htm");
//获取数据表对象
objILabel.LabelDatatable=ds.Tables[0];
//把这个页面上的变量用Hashtable对象传近模板类
objILabel.LabelHashtable=ht;
//返回解析结果
string aa=objILabel.LaberRepletText();
详细可看这三个文件的cs文件
WriteArticon.aspx -- 读模板 解析 写入文件 用于产生静态页面的新闻系统
ReturnText.aspx -- 读模板 解析 返回字符串 用与写经常要改变外观的页面,换皮肤的页 面。
************************************************************************************************
标签函数关联:
具体详细请看 Business.cs 文件
在逻辑层对应的类的静态构造器内,加如下代码。
//调用静态构造器,把标签体和执行函数委托做影射
//必须执行静态构造器
static Business()
{
Business _this=new Business();
//先临时产生一个这个类的对象为的是可以使用_this. 来点出所有的函数 :)
Business.AddLabel("无参书签", new Run_0(_this.show));
Business.AddLabel("一个参数书签",new Run_1(_this.tag));
Business.AddLabel("二个参数书签",new Run_2(_this.tag_two));
//书签和执行函数关联。放到书签解析类的静态构造函数内。
//是为了可以完全使用内存中的对象,不每次都执行
// "一个参数书签" 字符对应 public string tag(string aa) 函数
// ("一个参数书签",new Run_1(_this.tag)));
// 标签名 | |
// 一个参数就用Run_1委托。 |
// 对应的标签执行函数
// 0 个或多个上面有对应例子
}
具体详细请看 Business.cs 文件
************************************************************************************************
标签内loop循环介绍:
标签内通过一些特殊符号,可以实现非嵌套loop循环
//------------------------------------------------------------------------
{$loop(3,0,alter)$} //显示三行,从0行开始,如果有交替列,运行交替列
{$BlockItem$} //默认的循环行,
<td bgcolor="#33ccff">标题:{$dt[5][name]$} , 作者:{$一个参数:dt[dddf]$}</td>
{$/BlockItem$}
{$BlockAlterItem$} // 没有默认行标签对,有交替循标签对。就把交替循标签对当默认 // 行标签对
<td bgcolor="#ff6699">标题:{$dt[5][name]$} , 作者:{$一个参数:dt[dddf]$}</td>
{$/BlockAlterItem$}
{$BlockPatch$} //当要循环的行数大于Datatable内的行数时,用这里的内容补充显 //示 。 如果没有 “补充” 签对。那么当显示行数大于Datatable //中的行数时,将只显示Datatable中的行数
<td bgcolor="#33ccff">补充(里面也可以使用标签)</td>
{$/BlockPatch$}
{$BlockAlterPatch$} //没有补充标签对,有交替补充标签对。就把交替补充标签对当补 //充标签对
<td bgcolor="#ff6699">交替补充(里面也可以使用标签)</td>
{$/BlockAlterPatch$}
{$/loop$} //循环结束
//--------------------------------------------------------------
{$BlockItem$} {$/BlockItem$} :默认的循环行标签对
{$BlockAlterItem$} {$/BlockAlterItem$} :交替循环行标签对
{$BlockPatch$} {$/BlockPatch$} :默认补充行标签对
{$BlockAlterPatch$} {$/BlockAlterPatch$} :交替补充行标签对
//------------------------------------------------------
只有默认的循环行可以不加{$BlockItem$}标签对如
{$loop(3,0,alter)$}
<tr><td>{$函数标签$}</td></tr>
{$/loop$}
和
{$loop(3,0,alter)$}
{$BlockItem$}<tr><td>{$函数标签$}</td></tr>{$/BlockItem$}
{$/loop$}
是表示一样的效果。
//-------------------------------------------------------------
************************************************************************************************
loop参数说明:
{$loop(3,0,alter)$}
loop上一共有三个参数,可适当减少
第一个参数:
3:循环3次 ,没有表示循环全部
第二个参数:
2:从2开始,没有表示从0开始
第三个参数:
alter:交替
noalter:不交替 ,没有表示默认为交替,所以alter加不加是一样的
如果三个参数全不写,至少要保留一对空括号 {$loop()$}
表示循环Datatable内的行数,从0行开始,有补充就显示补充。
************************************************************************************************
建议模板不要大于85k,小心成为大尺寸对象。那可是二代对象
很高兴看见模板类和我自己的认识一起成长。
2006年5月22日
#
本次StringTempletReplet.dll组件更新了一些算法。主要是更依赖内存里静态变量内的数值。
做到了在不改变模板的条件下。缓存模板,缓存委托,缓存标签解析数据。但是这会更消耗一些内存。
为了可以动态更换模板,不得不每次检测文件的时间。在这个上消耗了不少时间。也许将来应该去掉
动态更换模板的功能,只提供一个通知模板类重新读哪个模板文件的接口。
取消了这个页面 (RetuenString.aspx --接受标签字符串 返回解析结果)
毕竟标签不会做成一种脚本语言。这个功能没有意义。
有人说不知道总么用这个模板类在此简要说一下:
模板类主要作用读的不是整页的模板。主要是读页面碎片模板。就是读碎片,解析,显示。
在web2.0站点,比如blog开发。用户自定义皮肤的页面。或者说全静态页新闻系统更新中
是有很大作用的。
标签的功能是通过标签解析函数来扩展的。所以模板类的速度不光是StringTempletReplet.dll组件
本身执行的速度。还要加上标签解析函数执行的时间。我例子提供的标签解析函数只是返回简单的字符串。
是为了方便说名一下。模板类做的只是提供一个舞台。并尽量让模板类执行的时间快一些。至于标签解析
函数是总么执行。用多少时间。那就是使用人的事情了。
正则替换模板类也写过。但是自己测试在长度为200多万的字符串上进行标签定位分析。比指针定位
要慢8倍以上。当模板字符串长度不断减小的时候。也许差距会漫漫减小。但是即使两个的标签定位时间
一样。根据字符串不可改变性,对一个字符串不断的替换会产生新的字符串。太消耗资源了。
Business.cs可以放在UI层 也可以放在逻辑层。只要继承了FunctionList类就可以。继承这个类只要
重写静态构造函数就可以了。在静态构造函数内建立标签和标签执行函数的对应。
其实在以前的版本里写过一种执行标签。就是在标签名前加"执行_"标记
{$执行_标签名:参数1:参数2:参数3::字符10$}
这样就不用重写静态构造函数。是通过反射来执行。但是速度很慢。后来就取消了。毕竟对模板类来说
速度是很关键的。
我没有固定的位置可以让大家下载,以前是把压缩文件该为gif图片。传到网易的个人资料里。但是
后来网易对图片进行检测了。让大家下不了。我在找新位置吧。图片位置会多变。
只要图片还没有被删除。可以下这个位置的图片 改为 Templet.rar 文件就好
2006年5月7日
#
做web开发也有几年了。自己在不同的公司有不同的认识。最近做blog项目。认识到了模板类在web开发中的作用。晚上在家。总想可以做一个专门的为asp.ne开发而设计的模板类。于是就写了这个模板类。
下面是里面的一个说明文件
//---------------------------------------------------------------------------------------------------------------------------//
介绍:
此模板类是为三层架构web站点开发而编写的。StringTempletReplet.dll组件
内包含模板类。StringTempletReplet命名空间内的模板类可以使用在UI层,也可
以使用在逻辑层。
*****************************************************************************
运行方法:
建立一个名叫 Templet 的虚拟目录指象解压后的 Templet 文件夹
运行内部的 RetuenString.aspx,ReturnText.aspx,WriteArticon.aspx,
LongLoop.aspx 页面。在页面对应的cs文件上有相应说明。
第一次打开页面应为要保留委托对象和模板文件到缓存中,所以真正的速度要看第
一次以后的。
*****************************************************************************
原理介绍:
一种标签替换的模板。使用了c#中的指针运算查找标签位置。
用委托对象指象标签对应的解析函数,并用静态对象缓存全部委托对象。
在不改变模板正文的情况下,缓存全部模板内容。可以动态更换模板。
****************************************************************************
标签介绍:
在成对特殊符号{$ 和 $} 之间的内容为标签
如
{$标签名:参数1:参数2:参数3::字符10$}
{$标签名:参数1:参数2::字节10$}
{$dt[5][name]$}
在标签内部通过 :: 符号把标签分为 (标签参数部分) 和 (命令控制部分) 两快
{$标签名:参数1:参数2:参数3::字节10$}
(标签参数部分) :: (命令控制部分)
在这两部分内以:号分割标签参数部分和命令控制部分
标签参数部分 ---第一个为标签名,就是标签解析函数的对应名称,以后的为函数的参数,
标签解析函数接受全部参数类型为string类型的,参数个数为0--20个的
函数,返回类型为string类型。参数可在标签上写死,也可以动态写入。
命令控制部分 ---现在只有两个命令符号 字符 和 字节 ,后带一个数字参数,表示截取标
签解析结果的长度, 如 字符10 字节10 。
我以后会在扩展其他的命令控制符号。
标签和函数对应请看Business.cs 文件内说明
标签具体使用规则请看Templet/templet/aa1.htm 模板内说明
具体调用规则请看项目中的这三个aspx页面
WriteArticon.aspx -- 读模板 解析 写入文件 用于产生静态页面的新闻系统
ReturnText.aspx -- 读模板 解析 返回字符串 用与写经常要改变外观的页面,
换皮肤的页面。可动态更换模板 。
******************************************************************************
标签动态取值:
标签解析函数除可以接受标签内传来的固定参数外。可以有三种方式接受动态参数
象模板类传递 Datatable 和 Hashtable 对象以后
(Datatable 从数据层获取 ,Hashtable 一般是页面变量 和其他变量)
1。 dt[5][name] ---- 表示取Datatable内5行name列上的数值,第一个为数字,
第二个是列名
2。 dt[name] ---- 在loop循环外表示取Datatable内0行name列上的数值,
一个参数表示列名
---- 在loop循环内表示取Datatable内name列上的数值,取那
些行通过loop标签的参数决定
3。 page[PageId] ----- 表示取Hashtable对象内PageId键上的数值,返回string类型
如 {$二个参数书签:dt[3][word]:page[UserId]::字符10$}
{$dt[5][name]$} {$dt[name]$} {$page[PageId]$}
或
{$dt[5][name]::字符10$} {$dt[name]::字符10$} {$page[PageId]::字符10$}
这样的标签表示直接在页面上显示对象内的数值
****************************************************************************
页面或类内调用模板类方法:
ReturnText.aspx -- 读模板 解析 返回字符串 用与写经常要改变外观的页面
换皮肤的页面
****************************************************************************
标签函数关联:
*****************************************************************************
标签内loop循环介绍:
标签内通过一些特殊符号,可以实现非嵌套loop循环
//------------------------------------------------------------------------
{$loop(3,0,alter)$} //显示三行,从0行开始,如果有交替列,运行交替列
{$BlockItem$} //默认的循环行,
<td bgcolor="#33ccff">标题:{$dt[5][name]$} , 作者:{$一个参数:dt[dddf]$}</td>
{$/BlockItem$}
{$BlockAlterItem$} // 交替循环行 当没有默认行标签对,有交替循标签对。就把交替循标签对当默认行标签对
<td bgcolor="#ff6699">标题:{$dt[5][name]$} , 作者:{$一个参数:dt[dddf]$}</td>
{$/BlockAlterItem$}
{$BlockPatch$} //当要循环的行数大于Datatable内的行数时,用这里的内容补充显示 。 如果没有 “补充” 标签对。那么当显示行数大于Datatable中的行数时,将只显示Datatable中的行数
<td bgcolor="#33ccff">补充(里面也可以使用标签)</td>
{$/BlockPatch$}
{$BlockAlterPatch$} //没有补充标签对,有交替补充标签对。就把交替补充标签对当补充标签对
<td bgcolor="#ff6699">交替补充(里面也可以使用标签)</td>
{$/BlockAlterPatch$}
{$/loop$} //循环结束
//--------------------------------------------------------------
{$BlockItem$} {$/BlockItem$} :默认的循环行标签对
{$BlockAlterItem$} {$/BlockAlterItem$} :交替循环行标签对
{$BlockPatch$} {$/BlockPatch$} :默认补充行标签对
{$BlockAlterPatch$} {$/BlockAlterPatch$} :交替补充行标签对
//------------------------------------------------------
如果只有默认的循环行可以不加{$BlockItem$}标签对
如
{$loop(3,0,alter)$}
<tr><td>{$函数标签$}</td></tr>
{$/loop$}
和
{$loop(3,0,alter)$}
{$BlockItem$}<tr><td>{$函数标签$}</td></tr>{$/BlockItem$}
{$/loop$}
是表示一样的效果
//-------------------------------------------------------------
{$loop(3,0,alter)$}
{$BlockAlterPatch$}
<tr><td>{$函数标签$}</td></tr>
{$/BlockAlterPatch$}
{$/loop$}
如果只有交替循环行标签对没有默认的循环行标签对那么交替循环行标签对将自动转换为
默认循环行标签对
//--------------------------------------------------------------
{$loop(3,0,alter)$}
{$BlockAlterPatch$}
<tr><td>{$函数标签$}</td></tr>
{$/BlockAlterPatch$}
{$/loop$}
如果只有交替补充行标签对没有默认补充行标签对那么交替补充行标签对将自动转换为
默认循环行标签对
**************************************************************************
loop参数说明:
{$loop(3,0,alter)$}
loop上一共有三个参数,可适当减少
第一个参数:
3:循环3次 ,没有表示循环全部
第二个参数:
2:从2开始,没有表示从0开始
第三个参数:
alter:交替
noalter:不交替 ,没有表示默认为交替,所以alter加不加是一样的
如果三个参数全不写,至少要保留一对空括号 {$loop()$}
表示循环Datatable内的行数
从0行开始,有补充就显示补充。
*************************************************************************
有更新了一下。主要是优化循环。
现在循环5