赏花归去马如飞, 去马如飞酒力微.
酒力微醒时已暮, 醒时已暮赏花归.---苏轼
我们力求页面层代码简洁并具有较好的可读性,在Asp.net MVC的平台上,我们以新的起点来实现这一目标.MvcContrib.FluentHtml和Spark ViewEngine给我们做出了榜样.本文将以MvcContrib.FluentHtml为例探究它的实现机制:Fluent Interface.
读过开篇的诗句,不知是否感受到文字之美.不仅仅是在文学作品中,在代码中,这种美一样存在.
在MvcContrib.FluentHtml的应用中,我们随处可以见到下面的代码:
上面对动态生成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创建页面元素的方式让我们很容易联想到StringBuilder的使用:
StringBuilder stringbuilder = new StringBuilder();
stringbuilder.Append("Hello").Append(" ").Append("World!");
Fulent Interface
这种实现编程方式就是"Fluent Interface",这并不是什么新概念,2005年Eric Evans 和Martin Fowler就为这种实现方式命名.源文档 <http://www.martinfowler.com/bliki/FluentInterface.html> 可以通过维基百科中对Fluent Interface的描述获得一个基本的了解:In software engineering, a fluent interface (as first coined by Eric Evans and Martin Fowler) is a way of implementing an object oriented API in a way that aims to provide for more readable code.
我们分解上面的话:
-
它是面向对象API的一种实现方式
- 目的是增加代码的可读性
既然我们最熟悉的是StringBuilder,我们就从这个线索追下去:打开Re
flector,很容易找到StringBuilder的Append方法:
阅读这段有两个特别要注意的点:1.方法的返回值是StringBuilder类型 2.最后一句:return this;为了深刻理解,我们写一个简单的StringBuilder:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicinterfaceIContentBuilder
{
voidWriteContent();
IContentBuilderAppend(stringpartialContent);
}
publicclassTestContentBuilder:IContentBuilder
{
stringtemp;
#regionIContentBuilderMembers
voidIContentBuilder.WriteContent()
{
Console.Write(temp);
}
IContentBuilderIContentBuilder.Append(stringpartialContent)
{
temp+=partialContent;
returnthis;
}
#endregion
}
……
//调用代码
IContentBuildert=newTestContentBuilder();
t.Append("test").Append("Hello").WriteContent();
跑一下代码,和StringBuilder效果是一样的.从上面的应用也可以看出:Fluent Interface经常用来完成对象的构造和属性赋值.
言归正传:FluentHTML
了解了Fluent Interface,我们来看一下MVCContrib.FluentHTML的实现,这里以TextBox为例进行考察,首先看一下它的继承关系:
public class TextBox : TextInput<TextBox>
public abstract class TextInput<T> : Input<T>, ISupportsMaxLength where T : TextInput<T>
public abstract class Input<T> : FormElement<T> where T : Input<T>, Ielement
泛型是一种高层次的算法抽象,我们就通过Input<T>一窥端倪:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicabstractclassInput<T>:FormElement<T>whereT:Input<T>,IElement
{
protectedobjectelementValue;
protectedInput(stringtype,stringname):base(HtmlTag.Input,name)
{
builder.MergeAttribute(HtmlAttribute.Type,type,true);
}
protectedInput(stringtype,stringname,MemberExpressionforMember,IEnumerable<IBehaviorMarker>behaviors)
:base(HtmlTag.Input,name,forMember,behaviors)
{
builder.MergeAttribute(HtmlAttribute.Type,type,true);
}
///<summary>
///Setthe'value'attribute.
///</summary>
///<paramname="value">Thevaluefortheattribute.</param>
publicvirtualTValue(objectvalue)
{
elementValue=value;
return(T)this;
}
///<summary>
///Setthe'size'attribute.
///</summary>
///<paramname="value">Thevaluefortheattribute.</param>
publicvirtualTSize(intvalue)
{
Attr(HtmlAttribute.Size,value);
return(T)this;
}
protectedoverridevoidPreRender()
{
Attr(HtmlAttribute.Value,elementValue);
base.PreRender();
}
}
以Size方法为例,可以看出这是一种典型的Fluent Interface实现:
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的实现代码里面我们没有看到对Lambda表达式的支持.那是在什么地方完成的呢?通过跟进,我们来到了ViewDataContainerExtensions,它是IViewDataContainer 的Extension Method:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->namespaceMvcContrib.FluentHtml
{
///<summary>
///ExtensionstoIViewDataContainer
///</summary>
publicstaticclassViewDataContainerExtensions
{
///<summary>
///GenerateanHTMLinputelementoftype'text'andsetitsvaluefromViewDatabasedonthenameprovided.
///</summary>
///<paramname="view">Theview.</param>
///<paramname="name">Valueofthe'name'attributeoftheelement.Alsousedtoderivethe'id'attribute.</param>
publicstaticTextBoxTextBox(thisIViewDataContainerview,stringname)
{
returnnewTextBox(name).Value(view.ViewData.Eval(name));
}
……
看一下return new TextBox(name).Value(view.ViewData.Eval(name));所以这里就成了TextBox定义方法链的第一步.
总结
为了能够在View中能够简洁清晰的构造HTML元素,Asp.net MVC中通过htmlHelper.InputHelper来实现页面元素的构造. 页面层所使用的<%= Html.TextBox("username") %>,HTML也是htmlHelper的Extension Method.相比较起来,htmlHelper提供了基础的页面控件定义和构造,而FluentHTML表现的更为灵活.除了FluentHTML,著名的Spark View Engine也有类似的实现,大家可以关注一下.
嗯哼,全文完.
P.S:最近要找工作了,有好机会联系我:mailto:ligaoren@gmail.com
分享到:
相关推荐
1 Getting Started with ASP.NET MVC 1.1 How ASP.NET MVC Works 1.2 Installing MVC 1.3 MVC in Five Minutes: Building Quote-O-Matic 2 Test-Driven Development 2.1 TDD Explained 2.2 Test-Driving ...
【ASP.NET编程知识】ASP.NET MVC5验证系列之Fluent Validation.docx
jQuery ASP.Net MVC Controls源码 项目介绍 一个ASP.Net MVC兼容包基础上完成控制jQuery和jqGrid框架。 * Ajax的分页,编辑,分格,批量更新 * 标准widgets,如DatePicker * 还有更多- 所有.NET Fluent-like配置和...
A Visual Studio 2013 project which shows how to use the Entity Framework 6 in an ASP.NET MVC 5 web application project, using the Code First development approach. The previous version that uses EF 5 ...
流利HTML 用于 Asp.net MVC 的 Fluent Html Helper
此存储库包含适用于 ASP.NET Core MVC 的 Fluent Assertions 扩展。 它由维护。 安装 将 NuGet 包添加到您的测试项目。 将 NuGet软件包添加到您的单元测试项目中: PM> Install-Package FluentAssertions....
主要为大家详细介绍了ASP.NET MVC5验证系列之Fluent Validation,感兴趣的小伙伴们可以参考一下
一套完整的框架及源代码,含数据初始数据,支持vs2010、2013,sql2008,学习真实项目及easyui、ko、fluent开发的资源
【ASP.NET编程知识】.NET验证组件Fluent Validation使用指南.docx
It also provide DbEntryDataSource for ASP.NET 2.0 and a Rails style MVC framework and a simple IoC framework. The samples of the release package all TESTED on Sql Server 2005 Express, MySql 5.0, ...
思想流使用ASP.NET MVC和NHibernate / Fluent开发的大型Web应用程序该应用程序具有独特的任务管理功能。 该方法基于时间管理书籍中的最佳技巧。任务类别该应用程序可以将任务分为以下几种类型: 想法-设计为最小且...
开源Codeplex其主页简介:该组件是一个轻量级的.NET类库,使用流畅的接口定义和lambda表达式为构建一个业务类的验证规则(A small validation library for .NET that uses a fluent interface and lambda ...
MyTested.AspNetCore.Mvc-流利测试ASP.NET Core MVC的库 钻石赞助商 金牌赞助商 特别赞助 项目简介 MyTested.AspNetCore.Mvc是一个强类型的单元测试库,提供了一个简单流畅的界面来测试框架,非常适合MVC和API方案。...
C# 7.1 and .NET Core 2.0 – Modern Cross-Platform Development – Third Edition 版本: Create powerful applications with .NET Standard 2.0, ASP.NET Core 2.0, … Visual Studio 2017 or Visual Studio Code ...
lucene-fluent-query-builder 使用 Lucene 的 API 构建查询可能有点麻烦,至少是冗长的。 此类尝试使用 Fluent 接口模式使编写查询尽可能简单。安装PM > Install-Package LrNet.Lucene.Fluent 首先,在使用查询构建...
.NET Standard 1.1至2.0的支持使您可以将其与以下各项一起使用: .Net Framework 4.5+ Xamarin iOS,Xamarin Android .Net核心 超人 Windows Phone 8.1 Windows 8.1 产品特点 REST API的现代异步http客户端。 ...
简介如今,RAD(快速应用程序开发)正在Swift发展。 有许多可用于开发Web应用程序或Web项目的框架。 我们可以使用Microsoft或任何其他框架的ASP.Net或ASP.Net MVC。 虽然,NancyFx对它有自己的支持