




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、話說上節(jié)聽的很郁悶,講的也郁悶,整個系列沒有詳細的Code,所以都有點懵。其實仔細看之前的幾節(jié)應該還是能夠理解整個思路的。我在這里再整理一遍:用戶訪問URL后-根據(jù)所有Page的URL規(guī)則(urIpattern)獲取當前Page,然后再根據(jù)page的Template,F(xiàn)ind出所有的Label(通過反射),然后遍歷這些Label,把得到的數(shù)據(jù)的Html替換掉Label本身的標簽代碼。最后整個Template就是要生成的HTML了。所以我們要明白Label是如何獲取工作才能獲取數(shù)據(jù)庫的數(shù)據(jù)的。一個Label可以理解成一個控件,那么控件必然會支持一些屬性(Parameter)和一些內(nèi)容(Field
2、)。我們上節(jié)就是在講怎么來解析parameter,因為有些特殊的parameter,所以設計的時候設計了parameter的基類,特殊的則是子類。同樣,field是具體的要展現(xiàn)在HTML代碼中的字段,比如中的field:Title/,這就是一個字段,我們的模版引擎的工作就是把他替換掉應該展現(xiàn)的標題,而如何才能工作?我們就得設計Field的整個邏輯。在替換循環(huán)的過程中使用field類。但是,我今天不講Field了,因為這樣講大家還是糊涂依舊。今天我們就來設計一個Article:List的初級版。我覺得或許從實例講解大家更容易理解設計的理念。0K,那就開始設計一個Article.List,我們最熟
3、悉的文章列表。/簡單的循環(huán)列表Article:ListTop=10CategoryId=5field:Title/Article:List想象一下Repeater,有個ItemTemplate,那么對于List這個Label來說,他的ItemTemplate顯然就是Template屬性。那么如果我們獲取到數(shù)據(jù)源后直接foreach替換掉所有的field即可。代碼大概如下:/獲取要展示的HTML代碼/publicoverridestringGetRenderHtml()varhtml=TemplateString;foreach(vararticleinGetDataSource()foreac
4、h(varfieldinFields)html=html.Replace(field.Html,field.GetValue(article);returnhtml;從上面的方法中,我們可以看到替換的機制是每一行數(shù)據(jù)都要執(zhí)行一次所有字段的替換(所以之前有提過在構(gòu)造嵌套的時候為了防止Field混亂要處理TemplateString),最后返回html。我們還能看到一些未知的方法和字段:GetDataSource(),Field.Html,Field.GetValue(),這些已經(jīng)暴露了我們的Field設計的部分內(nèi)容。我們先看GetDataSource()是什么?日代碼/獲取Article列表/p
5、rivateIEnumerableGetDataSource()varparameter=newArticleQueryParameter();/構(gòu)造查詢的參數(shù)returnArticleDataHelper.GetList(parameter);/查詢參數(shù)基類/publicclassQueryParameterpublicintPageSizeget;set;publicintPageIndexget;set;publicintRecordCountget;set;publicstringSearchKeyget;set;/文章查詢類/publicclassArticleQueryParame
6、terpublicQueryParameterPageParameterget;set;publicDateTimePostTimeget;set;publicintCategoryIdget;set;publicintTopget;set;/文章獲取數(shù)據(jù)類/publicclassArticleDataHelperpublicstaticIEnumerableGetList(ArticleQueryParameterparameter)returnnull;其實就是獲取ArticleList的數(shù)據(jù)源,具體的實現(xiàn)方式大家可能都不一樣,但Article.List最終需要這么一個數(shù)據(jù)獲取的方法,然而
7、這個方法都需要接受一些查詢條件的參數(shù),這些參數(shù)都來自Parameters!現(xiàn)在我們來填充GetDataSource()的參數(shù)構(gòu)造部分。privateIEnumerableGetDataSource()varparameter=newArticleQueryParameter();/構(gòu)造查詢的參數(shù)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轉(zhuǎn)成T類型。這就是Parameter所用到的地方之
9、一。另外可以看到Field具體Html屬性和GetValue方法,而且GetValue接受了當前Article實體作為參數(shù)(不接受參數(shù)的話,我們怎么得到某個字段的值呢:)。整個List流程應該比較清楚了吧,獲取數(shù)據(jù)源,然后循環(huán)數(shù)據(jù),每行再去替換所有的Field,最后把拼接好的HTML返回。當然這是List,如果是其他的標簽可能就是另外一個處理辦法。比如System.Include標簽,他的工作就是嵌入一個用戶控件(PartialTemplate),那么他的處理邏輯和List就完全不一樣(他是先根據(jù)templateid參數(shù)的值獲取template,然后再把自己所有的Parameters傳遞給這個
10、template里的所有標簽,最后再把這個template替換后的結(jié)果作為自己的結(jié)果返回,他沒有循環(huán))。所以我們的具體控件邏輯都是大相徑庭的,但最終都是要返回替換后的HTML,但所有的List卻都是差別多的,無非就是不同的數(shù)據(jù)源進行循環(huán)。所以對于List我們應該進行抽象,把公共部分提取出來,盡量讓每個具體的Label更明確職責。如何抽象呢?那就看看有沒有可提取的公共部分。所有的List都可能會有分頁,所以ListBase應該有PageParameter,所有的List都會去循環(huán)DataSoruce,所以ListBase默認實現(xiàn)了DataSource循環(huán),但是增加了一個方法那就是GetDataS
11、ource。這個方法是抽象的,所有的List必須實現(xiàn)。日代碼/循環(huán)標簽基類/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里我也做了點細微的調(diào)整,就是把Field的GetValue的參數(shù)拿掉了,換成了成員,這樣更明白些。你可能會有一些疑點:為什么設計為抽象而不是虛方法或接口?所有子類的實現(xiàn)方法都不一致,沒有可提取部分,所以虛函數(shù)沒有意義,如果單獨抽象成接口,則所有子類必須繼承此接口,因為GetRenderHtml和該方法緊密結(jié)合,foreach里需要顯式轉(zhuǎn)換為接口才能調(diào)用,完全
13、沒有意義。為什么是GetDataSource方法,而不是公開一個DataSource成員?如果需要Set呢?還要增加一個SetDataSource?其實這個我考慮過,很少有Set的情況,因為標簽都是自動生成的沒有外部去干擾(Set),但不能否認以后完全沒有,如果設為成員,則必須有一個可get的地方,要么是abstract,那樣也會把setabstract,要么就在Init里給set先,那也得有一個抽象的set方法。所以考慮現(xiàn)狀還是使用一個方法最為合適。另外一點就是為什么用了dynamic,而不是T。首先不能是T,如果是T,則GetRenderHtml調(diào)用時也需要指明T,則整個ListBase就
14、要變成泛型類ListBase,除非base不執(zhí)行GetDataSource調(diào)用。為什么不能用ListBase?因為有些GetDataSource會用linq返回匿名類型集合,子類無法確定返回的具體類型名稱,所以就不能繼承ListBaseListBase。但我們可以用dynamic,動態(tài)類型,到真正執(zhí)行時可以確定T就行,這個不用我們操心,然而object顯然略遜一籌了。這樣一來,Article的List只需要實現(xiàn)GetDataSource就行了。這只是最簡單的List雛形,假如說我還需要像Repeater控件那樣,有headtemplateitemtemplatefoottemplatealte
15、rtemplatespacetemplate怎么辦?這個就需要定義子標簽類了。這里我就不多說了,其實很簡單,就是再定義幾個Label,他們又各自的獲取Html的方法,我們最后組合起來就行。自需要注意List的Template和Field已經(jīng)沒了,都屬于子標簽了。而且像交替執(zhí)行的(Item和Alter)需要再循環(huán)里給他們隔行賦值。下面是我以前寫的代碼,雖然比較難看,不太00,但能說明實現(xiàn)的邏輯:田日代碼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ài)類型,到真正執(zhí)行時可以確定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ài)類型,到真正執(zhí)行時可以確定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)/替換循環(huán)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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024-2025學年五年級下冊數(shù)學《露在外面的面》(教案)
- 《定風波 莫聽穿林打葉聲》歷年中考古詩欣賞試題匯編(截至2022年)
- 2024年作物收獲機械項目資金籌措計劃書代可行性研究報告
- 2024年歌舞廳娛樂服務項目資金需求報告
- 2025年湖南工業(yè)職業(yè)技術學院單招職業(yè)適應性測試題庫及參考答案
- 2024年注射用骨肽投資申請報告代可行性研究報告
- 深圳高級中學(集團)2025屆高三第三次診斷考數(shù)學試題+答案
- 2025年鶴壁職業(yè)技術學院單招職業(yè)傾向性測試題庫完美版
- 二零二五年度精裝修公寓轉(zhuǎn)租合同電子版
- 2025年度工傷事故責任劃分與賠償方案合同
- 美術第二課堂活動方案2篇
- (名師整理)部編人教版語文初中課內(nèi)古詩文大全(五四制)
- 非常好的精益生產(chǎn)案例-值得借鑒
- 東南亞潤滑油市場研究報告和展望
- 煤礦安全知識300問 煤礦職工每日一題
- 《0-3歲嬰幼兒教育》課程教學大綱
- 2023年廣東醫(yī)科大學專插本中藥學真題
- GB/T 5392-2004林業(yè)機械油鋸技術條件
- GB/T 26535-2011國家重要濕地確定指標
- GA/T 1133-2014基于視頻圖像的車輛行駛速度技術鑒定
- 食品安全 PPT課件7農(nóng)獸藥化學性污染對食品安全性的影響
評論
0/150
提交評論