這篇文章將為大家詳細講解有關(guān)如何理解ASP.NET MVC中的FluentHtml與連續(xù)接口,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
在濉溪等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站制作 網(wǎng)站設計制作按需求定制開發(fā),公司網(wǎng)站建設,企業(yè)網(wǎng)站建設,成都品牌網(wǎng)站建設,網(wǎng)絡營銷推廣,成都外貿(mào)網(wǎng)站制作,濉溪網(wǎng)站建設費用合理。
我們力求頁面層代碼簡潔并具有較好的可讀性,在ASP.NET MVC的平臺上,我們以新的起點來實現(xiàn)這一目標.MvcContrib.FluentHtml和Spark ViewEngine給我們做出了榜樣.本文將以MvcContrib.FluentHtml為例探究它的實現(xiàn)機制:Fluent Interface.
在MvcContrib.FluentHtml的應用中,我們隨處可以見到下面的代碼:
< %= this.TextBox(x => x.Person.Name).Title("Enter the person's name").Label("Name:") %> …… < %= this.Select(x => x.Person.Gender).Options(Model.Genders).Size(5).Label("Gender:") .Title("Select the person's gender") %>
瀏覽器中生成的代碼為:
< LABEL id=Person_Name_Label for=Person_Name>Name:< /LABEL> < INPUT id=Person_Name title="Enter the person's name" value=Jeremy maxLength=50 name=Person.Name> . < SELECT id=Person_Gender title="Select the person's gender" size=5 name=Person.Gender>< OPTION selected value=M>Male< /OPTION>< OPTION value=F>Female< /OPTION>< /SELECT>
上面對動態(tài)生成TextBox和Select的代碼很有意思,我們使用普通的方式在頁面上生成同樣的客戶端代碼,CS代碼大致是這樣的:
Label label = new Label(); label.Text = "Name"; TextBox textbox= new TextBox(); textbox.ToolTip ="Enter the person's name"; textbox.ID = "No.10001"; textbox.ID = "Person.Name";
而FluentHtml創(chuàng)建頁面元素的方式讓我們很容易聯(lián)想到StringBuilder的使用:
StringBuilder stringbuilder = new StringBuilder(); stringbuilder.Append("Hello").Append(" ").Append("World!");
Fulent Interface 這種實現(xiàn)編程方式就是"Fluent Interface",這并不是什么新概念,2005年Eric Evans 和Martin Fowler就為這種實現(xiàn)方式命名.源文檔
我們分解上面的話:
它是面向?qū)ο驛PI的一種實現(xiàn)方式,目的是增加代碼的可讀性.。既然我們最熟悉的是StringBuilder,我們就從這個線索追下去:打開Reflector,很容易找到StringBuilder的Append方法:
public StringBuilder Append(string value) { if (value != null) { string stringValue = this.m_StringValue; IntPtr currentThread = Thread.InternalGetCurrentThread(); if (this.m_currentThread != currentThread) { stringstringValue = string.GetStringForStringBuilder(stringValue, stringValue.Capacity); } int length = stringValue.Length; int requiredLength = length + value.Length; if (this.NeedsAllocation(stringValue, requiredLength)) { string newString = this.GetNewString(stringValue, requiredLength); newString.AppendInPlace(value, length); this.ReplaceString(currentThread, newString); } else { stringValue.AppendInPlace(value, length); this.ReplaceString(currentThread, stringValue); } } return this; }
閱讀這段有兩個特別要注意的點:1.方法的返回值是StringBuilder類型 2.***一句:return this;為了深刻理解,我們寫一個簡單的StringBuilder:
public interface IContentBuilder { void WriteContent(); IContentBuilder Append(string partialContent); } public class TestContentBuilder : IContentBuilder { string temp; #region IContentBuilder Members void IContentBuilder.WriteContent() { Console.Write(temp); } IContentBuilder IContentBuilder.Append(string partialContent) { temp += partialContent; return this; } #endregion } … … //調(diào)用代碼 IContentBuilder t = new TestContentBuilder(); t.Append("test").Append("Hello").WriteContent();
跑一下代碼,和StringBuilder效果是一樣的.從上面的應用也可以看出:Fluent Interface經(jīng)常用來完成對象的構(gòu)造和屬性賦值.
言歸正傳:FluentHTML了解了Fluent Interface,我們來看一下MVCContrib.FluentHTML的實現(xiàn),這里以TextBox為例進行考察,首先看一下它的繼承關(guān)系:
public class TextBox : TextInput public abstract class TextInput : Input, ISupportsMaxLength where T : TextInput public abstract class Input : FormElement where T : Input, Ielement
泛型是一種高層次的算法抽象,我們就通過Input
public abstract class Input : FormElement where T : Input, IElement { protected object elementValue; protected Input(string type, string name) : base(HtmlTag.Input, name) { builder.MergeAttribute(HtmlAttribute.Type, type, true); } protected Input(string type, string name, MemberExpression forMember, IEnumerable behaviors) : base(HtmlTag.Input, name, forMember, behaviors) { builder.MergeAttribute(HtmlAttribute.Type, type, true); } /// /// Set the 'value' attribute. /// /// The value for the attribute. public virtual T Value(object value) { elementValue = value; return (T)this; } /// /// Set the 'size' attribute. /// /// The value for the attribute. public virtual T Size(int value) { Attr(HtmlAttribute.Size, value); return (T)this; } protected override void PreRender() { Attr(HtmlAttribute.Value, elementValue); base.PreRender(); } } 以Size方法為例,可以看出這是一種典型的Fluent Interface實現(xiàn): public virtual T Size(int value) { Attr(HtmlAttribute.Size, value); return (T)this; }
分析到這里,上面的語句中還有一點比較奇怪,就是Lambda表達式的部分:
this.TextBox(x => x.Person.Name).Title("Enter the person's name").Label("Name:")
TextBox的實現(xiàn)代碼里面我們沒有看到對Lambda表達式的支持.那是在什么地方完成的呢?通過跟進,我們來到了ViewDataContainerExtensions,它是IViewDataCon
namespace MvcContrib.FluentHtml { /// /// Extensions to IViewDataContainer /// public static class ViewDataContainerExtensions { /// /// Generate an HTML input element of type 'text' and set its value from ViewData based on the name provided. /// /// The view. /// Value of the 'name' attribute of the element.Also used to derive the 'id' attribute. public static TextBox TextBox(this IViewDataContainer view, string name) { return new TextBox(name).Value(view.ViewData.Eval(name)); } … …
tainer 的Extension Method:
看一下return new TextBox(name).Value(view.ViewData.Eval(name));所以這里就成了TextBox定義方法鏈的***步.
FluentHtml與連續(xù)接口總結(jié)
為了能夠在View中能夠簡潔清晰的構(gòu)造HTML元素,Asp.net MVC中通過htmlHelper.InputHelper來實現(xiàn)頁面元素的構(gòu)造. 頁面層所使用的<%=>,HTML也是htmlHelper的Extension Method.相比較起來,htmlHelper提供了基礎(chǔ)的頁面控件定義和構(gòu)造,而FluentHTML表現(xiàn)的更為靈活。
關(guān)于如何理解ASP.NET MVC中的FluentHtml與連續(xù)接口就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。