CMS系统模板引擎设计:Label应用初探_第1页
CMS系统模板引擎设计:Label应用初探_第2页
CMS系统模板引擎设计:Label应用初探_第3页
CMS系统模板引擎设计:Label应用初探_第4页
CMS系统模板引擎设计:Label应用初探_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、话说上节听的很郁闷,讲的也郁闷,整个系列没有详细的Code,所以都有点懵。其实仔细看之前的几节应该还是能够理解整个思路的。我在这里再整理一遍:用户访问URL后-根据所有Page的URL规则(urIpattern)获取当前Page,然后再根据page的Template,Find出所有的Label(通过反射),然后遍历这些Label,把得到的数据的Html替换掉Label本身的标签代码。最后整个Template就是要生成的HTML了。所以我们要明白Label是如何获取工作才能获取数据库的数据的。一个Label可以理解成一个控件,那么控件必然会支持一些属性(Parameter)和一些内容(Field

2、)。我们上节就是在讲怎么来解析parameter,因为有些特殊的parameter,所以设计的时候设计了parameter的基类,特殊的则是子类。同样,field是具体的要展现在HTML代码中的字段,比如中的field:Title/,这就是一个字段,我们的模版引擎的工作就是把他替换掉应该展现的标题,而如何才能工作?我们就得设计Field的整个逻辑。在替换循环的过程中使用field类。但是,我今天不讲Field了,因为这样讲大家还是糊涂依旧。今天我们就来设计一个Article:List的初级版。我觉得或许从实例讲解大家更容易理解设计的理念。0K,那就开始设计一个Article.List,我们最熟

3、悉的文章列表。/简单的循环列表Article:ListTop=10CategoryId=5field:Title/Article:List想象一下Repeater,有个ItemTemplate,那么对于List这个Label来说,他的ItemTemplate显然就是Template属性。那么如果我们获取到数据源后直接foreach替换掉所有的field即可。代码大概如下:/获取要展示的HTML代码/publicoverridestringGetRenderHtml()varhtml=TemplateString;foreach(vararticleinGetDataSource()foreac

4、h(varfieldinFields)html=html.Replace(field.Html,field.GetValue(article);returnhtml;从上面的方法中,我们可以看到替换的机制是每一行数据都要执行一次所有字段的替换(所以之前有提过在构造嵌套的时候为了防止Field混乱要处理TemplateString),最后返回html。我们还能看到一些未知的方法和字段:GetDataSource(),Field.Html,Field.GetValue(),这些已经暴露了我们的Field设计的部分内容。我们先看GetDataSource()是什么?日代码/获取Article列表/p

5、rivateIEnumerableGetDataSource()varparameter=newArticleQueryParameter();/构造查询的参数returnArticleDataHelper.GetList(parameter);/查询参数基类/publicclassQueryParameterpublicintPageSizeget;set;publicintPageIndexget;set;publicintRecordCountget;set;publicstringSearchKeyget;set;/文章查询类/publicclassArticleQueryParame

6、terpublicQueryParameterPageParameterget;set;publicDateTimePostTimeget;set;publicintCategoryIdget;set;publicintTopget;set;/文章获取数据类/publicclassArticleDataHelperpublicstaticIEnumerableGetList(ArticleQueryParameterparameter)returnnull;其实就是获取ArticleList的数据源,具体的实现方式大家可能都不一样,但Article.List最终需要这么一个数据获取的方法,然而

7、这个方法都需要接受一些查询条件的参数,这些参数都来自Parameters!现在我们来填充GetDataSource()的参数构造部分。privateIEnumerableGetDataSource()varparameter=newArticleQueryParameter();/构造查询的参数parameter.CategoryId=ParametersCategoryId.ConvertToInt(0);parameter.Top=ParametersTop.ConvertToInt(ParametersPageSize.ConvertToInt(0);varpageIndex=Param

8、etersPageIndex.ConvertToInt(1);if(pageIndex1)parameter.PageParameter=newQueryParameterPageIndex=pageIndex,PageSize=parameter.Top;returnArticleDataHelper.GetList(parameter);Parameters是Label的ParameteCollection,他可以通过索引直接访问具体的parameter。ConvertTo(TdefaultValue)是可以将parameter的value转成T类型。这就是Parameter所用到的地方之

9、一。另外可以看到Field具体Html属性和GetValue方法,而且GetValue接受了当前Article实体作为参数(不接受参数的话,我们怎么得到某个字段的值呢:)。整个List流程应该比较清楚了吧,获取数据源,然后循环数据,每行再去替换所有的Field,最后把拼接好的HTML返回。当然这是List,如果是其他的标签可能就是另外一个处理办法。比如System.Include标签,他的工作就是嵌入一个用户控件(PartialTemplate),那么他的处理逻辑和List就完全不一样(他是先根据templateid参数的值获取template,然后再把自己所有的Parameters传递给这个

10、template里的所有标签,最后再把这个template替换后的结果作为自己的结果返回,他没有循环)。所以我们的具体控件逻辑都是大相径庭的,但最终都是要返回替换后的HTML,但所有的List却都是差别多的,无非就是不同的数据源进行循环。所以对于List我们应该进行抽象,把公共部分提取出来,尽量让每个具体的Label更明确职责。如何抽象呢?那就看看有没有可提取的公共部分。所有的List都可能会有分页,所以ListBase应该有PageParameter,所有的List都会去循环DataSoruce,所以ListBase默认实现了DataSource循环,但是增加了一个方法那就是GetDataS

11、ource。这个方法是抽象的,所有的List必须实现。日代码/循环标签基类/publicabstractclassListBase:LabelpublicQueryParameterPageParameterget;set;publicabstractIEnumerableGetDataSource();publicoverridestringGetRenderHtml()vardataSource=GetDataSource();if(dataSource=null)returnstring.Empty;varhtml=TemplateString;foreach(vardataItemin

12、dataSource)foreach(varfieldinFields)field.Data=dataItem;html=html.Replace(field.Html,field.GetValue();returnhtml;foreach里我也做了点细微的调整,就是把Field的GetValue的参数拿掉了,换成了成员,这样更明白些。你可能会有一些疑点:为什么设计为抽象而不是虚方法或接口?所有子类的实现方法都不一致,没有可提取部分,所以虚函数没有意义,如果单独抽象成接口,则所有子类必须继承此接口,因为GetRenderHtml和该方法紧密结合,foreach里需要显式转换为接口才能调用,完全

13、没有意义。为什么是GetDataSource方法,而不是公开一个DataSource成员?如果需要Set呢?还要增加一个SetDataSource?其实这个我考虑过,很少有Set的情况,因为标签都是自动生成的没有外部去干扰(Set),但不能否认以后完全没有,如果设为成员,则必须有一个可get的地方,要么是abstract,那样也会把setabstract,要么就在Init里给set先,那也得有一个抽象的set方法。所以考虑现状还是使用一个方法最为合适。另外一点就是为什么用了dynamic,而不是T。首先不能是T,如果是T,则GetRenderHtml调用时也需要指明T,则整个ListBase就

14、要变成泛型类ListBase,除非base不执行GetDataSource调用。为什么不能用ListBase?因为有些GetDataSource会用linq返回匿名类型集合,子类无法确定返回的具体类型名称,所以就不能继承ListBaseListBase。但我们可以用dynamic,动态类型,到真正执行时可以确定T就行,这个不用我们操心,然而object显然略逊一筹了。这样一来,Article的List只需要实现GetDataSource就行了。这只是最简单的List雏形,假如说我还需要像Repeater控件那样,有headtemplateitemtemplatefoottemplatealte

15、rtemplatespacetemplate怎么办?这个就需要定义子标签类了。这里我就不多说了,其实很简单,就是再定义几个Label,他们又各自的获取Html的方法,我们最后组合起来就行。自需要注意List的Template和Field已经没了,都属于子标签了。而且像交替执行的(Item和Alter)需要再循环里给他们隔行赋值。下面是我以前写的代码,虽然比较难看,不太00,但能说明实现的逻辑:田日代码publicclassListLabelBase:LabelBasepublicLabelHtmlAttrsHtmlAttrsget;set;publicPageParameterPageget;

16、set;publicListTemplateItemTemplateget;set;publicListTemplateAlterTemplateget;setpublicListTemplateHeadTemplateget;set;publicListTemplateFootTemplateget;set;publicListTemplateNullTemplateget;set;publicSpaceTemplateSpaceTemplateget;set;publicintRowsget;set;publicoverridevoidInit()HtmlAttrs=newLabelHtm

17、lAttrs(Attrs);Rows=Attrs.GetAttribute(Rows,0);InitTemplates();Page=newPageParameterPageIndex=Attrs.GetParameter(PageIndex,1),PageSize=Attrs.GetAttribute(PageSize,Rows),OrderBy=Attrs.GetAttribute(Sort,string.Empty),IsASC=Attrs.GetAttribute(asc,false);Fields.SetAllBeginReplace(field,obj)=if(obj!=null)

18、vartmp=(ListItem)obj).Item.GetPropertyValue(field.Name);field.Value=tmp=null?string.Empty:tmp.ToString(););FieldsItemIndex.SetBeginReplace(field,obj)=field.Value=obj=null?string.Empty:(ListIteListBaseListBase。但我们可以用dynamic,动态类型,到真正执行时可以确定T就行,这个不用我们操心,m)obj).Index).ToString(););/实例化PageFieldFields.Ov

19、errideField(Page,page=newPageFieldGetRecordCount=()=Page.RecordCount,PageSize=Page.PageSize,PageIndex=Page.PageIndex,Attrs=page.Attrs,Template=page.Template);publicvirtualvoidInitTemplates()varmatches=Regexs.ListTemplatePattern.Matches(Template);foreach(Matchminmatches)vartemplate=m.Groupstemplate=n

20、ull?string.Empty:m.Groupstemplate.Value;varvalue=m.Groupsvalue=null?string.Empty:m.Groupsvalue.Value;varhtml=m.Groups0.Value;if(string.IsNullOrEmpty(html)continue;ListBaseListBase。但我们可以用dynamic,动态类型,到真正执行时可以确定T就行,这个不用我们操心,emplate,Htmlt=template,t=template,emplate,Htmlemplate,Htmlemplate,Htmlemplate,

21、Htmlt=template,t=template,emplate,Htmlemplate,Htmlemplate,Htmlswitch(m.Groupsname.Value)caseitem:ItemTemplate=newListTemplateContent=t=html;break;casealter:AlterTemplate=newListTemplateContenHtml=html;break;casespace:SpaceTemplate=newSpaceTemplateContenHtml=html,Length=value.ToInt(1);break;casehead:

22、HeadTemplate=newListTemplateContent=t=html;break;casefoot:FootTemplate=newListTemplateContent=t=html;break;casenull:NullTemplate=newListTemplateContent=t=html;break;if(ItemTemplate=null&!String.IsNullOrEmpty(Template)ItemTemplate=AlterTemplate?newListTemplateContent=Template,Html=Template;return;/获取

23、替换后的Html/publicvirtualstringGetListContent(IEnumerabledataSoruce)if(dataSoruce=null|dataSoruce.Count()=0)returnstring.Empty;varlist=dataSoruce.ToList();varfirstItem=list.Count=0?default(T):list0;#regionHeadTemplateif(HeadTemplate!=null)varheadContent=ReplaceTemplate(HeadTemplate.Content,newListItemI

24、ndex=0,Item=firstItem);Template=Template.Replace(HeadTemplate.Html,headContent);#endregion#regionFootTemplateif(FootTemplate!=null)varfootContent=ReplaceTemplate(FootTemplate.Content,newListItemIndex=0,Item=firstItem);Template=Template.Replace(FootTemplate.Html,footContent);#endregion#regionItemTemp

25、lateif(ItemTemplate!=null)/替换循环varlistContent=string.Empty;if(list.Count0)varitemIndex=(Page=null?0:(Page.PageIndex-1)*Page.PageSize)+1;if(HtmlAttrs.Cols1)listContent+=HtmlAttrs.PanelBegin;varrowNumber0;varrowNumber0;foreach(varmodelinlist)vartmpTemplate=ItemTemplate.Content;if(AlterTemplate!=null&rowNumber%2=0)tmpTemplate=AlterTemplate.Content;listContent+=HtmlAttrs.RowBegin;for(varc=0;cHtmlAttrs.Cols;c+)listContent+=HtmlAttrs.CellBegin;listContent+=ReplaceTemplate(tmpTemplate,newListItemItem=model,Index=itemIndex);listCo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论