一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

二十行C#代碼打造Ruby Markup Builder

  從.NET誕生之日起就有了XML類庫,但是從使用上來說非常不方便。例如我們需要構(gòu)造一個XML文檔時,使用DOM API就要這樣搞:

var xmlDoc = new XmlDocument();var rootEle = xmlDoc.CreateElement("persons");xmlDoc.AppendChild(rootEle);var person1 = xmlDoc.CreateElement("person");person1.InnerText = "Tom";var person1Age = xmlDoc.CreateAttribute("age");person1Age.Value = "10";person1.Attributes.Append(person1Age);rootEle.AppendChild(person1);var person2 = xmlDoc.CreateElement("person");person2.InnerText = "Jerry";var person2Age = xmlDoc.CreateAttribute("age");person2Age.Value = "8";person2.Attributes.Append(person2Age);rootEle.AppendChild(person2);

  別看這么多行代碼,但實際上它只構(gòu)造了這么簡單的一個XML:

<persons>  <person age="10">Tomperson>  <person age="8">Jerryperson>persons>

  我承認(rèn),DOM API的確非常嚴(yán)謹(jǐn)(如XmlDocument和XmlElement的歸屬關(guān)系),非常符合定義,也非常的面向?qū)ο螅沁@易用性也實在太差了。記得在03還是04年的時候,我為在為項目做一個編輯XML文檔的WinForm應(yīng)用程序,當(dāng)時也不像現(xiàn)在那么容易想到“偷懶”的法門,而VS 2003也不像VS 2005/2008那么好用,因此可謂做的勞心費神。這個情況在.NET 2.0中也沒有得到改變,直到有一天,LINQ to XML隨.NET 3.5橫空出世,于是乎XML的生活一下子變得美好了很多。例如上面的功能只需寥寥數(shù)行便可以實現(xiàn):

var xmlDoc = new XElement("persons",    new XElement("person",        "Tom",        new XAttribute("age", 10)),    new XElement("person",        "Jerry",        new XAttribute("age", 8))); 

  雖然LINQ to XML一直是所謂C# 3.0中LINQ特性的一部分,與LINQ to SQL,LINQ to Object及LINQ to……某個別的并列,但我始終認(rèn)為LINQ to XML實則還是LINQ to Object的一種特殊形式,只是它用于操作XML而已。它的一切都是System.Xml.Linq命名空間下相關(guān)類庫(如XElement)在起作用,不關(guān)LINQ什么事情。XElement等相關(guān)類型大大簡化了我們的開發(fā),與DOM API相比,無論是XML的構(gòu)造還是讀取都容易了許多。不過俗話說得好:“不怕不識貨,就怕貨比貨”,這樣的API與Ruby Markup Builder相比還是有明顯差距。請看:

builder = Builder::XmlMarkup.newxml = builder.persons { |b|    b.person("Tom", :age => "10")    b.person("Jerry", :age => "8")}

  請看上面這段代碼,它自然沒有使用Ruby語言的標(biāo)準(zhǔn)著色方式。我著色的目的是體現(xiàn)這個構(gòu)造方式中的“噪音”——也就是與XML內(nèi)容無關(guān)的部分。從中可以發(fā)現(xiàn),Ruby不愧是一種噪音較少的語言,如果您嘗試使用這個方式來觀察C#中LINQ to XML的做法,就會發(fā)現(xiàn)兩者之間的確有明顯的差距。當(dāng)然,如果使用VB.NET的XML Literal可能噪音也很少,但是在我看來,XML Literal在XML構(gòu)造方面的表現(xiàn)有些羅嗦,例如它需要開發(fā)人員同時提供元素的開始標(biāo)簽和閉合標(biāo)簽,可能在IDE的幫助下此類代碼輸入較為簡單,但是代碼還是略顯冗余。

  但是我們這些可憐的C#程序員難道只有在一邊眼饞的份嗎?不見得,我們也可以來“享受”一把:

dynamic b = new XmlMarkupBuilder();XElement xml =    b.persons(        b.person("Tom", age: 10),        b.person("Jerry", age: 8));

  哇,這是什么,怎么代碼那么簡單。很明顯,從dynamic關(guān)鍵字上可以看出,這是C# 4.0中新增的功能。您可能會想“原來.NET 4.0對XML又有增強(qiáng)了”……其實并非如此,這是我們自己擴(kuò)展的功能。不過這應(yīng)該算是更好的消息,因為這說明我們已經(jīng)有能力自行擴(kuò)展,自行設(shè)計這樣的API了——這可是“漁”,比“魚”可要值錢多了。而實現(xiàn)這樣的功能也只需要短短二十幾行C#代碼:

public class XmlMarkupBuilder : DynamicObject{    public override bool TryInvokeMember(InvokeMemberBinder binder, 
object
[] args, out object result) { XElement xml = new XElement(binder.Name); var attrCount = binder.CallInfo.ArgumentNames.Count; var elementCount = args.Length - attrCount; for (int i = 0; i < elementCount; i++) { xml.Add(args[i]); } for (var i = 0; i < attrCount; i++) { var attrName = binder.CallInfo.ArgumentNames[i]; if (attrName[0] == '@') attrName = attrName.Substring(1); xml.Add(new XAttribute(attrName, args[i + elementCount])); } result = xml; return true; }}

  DynamicObject是個特殊的對象,簡單地說它的行為可以被“擴(kuò)展”——是如動態(tài)語言般真正的擴(kuò)展,而非靜態(tài)的多態(tài)。當(dāng)我們使用dynamic修飾變量后,在它之上的方法調(diào)用會由編譯器和DLR配合出不一樣的行為。例如,我們在調(diào)用一個方法的時候,DLR會先檢查這個動態(tài)對象上是否存在符合這個簽名的方法,存在則最好,否則便會調(diào)用TryInvokeMember來“執(zhí)行”一個動態(tài)方法,而它的參數(shù)便是此次調(diào)用的全部信息。這樣的做法被稱為“Method Missing”操作,事實上Ruby Markup Builder也是使用Ruby對象中的這個特性來實現(xiàn)“調(diào)用什么方法,便生成什么元素”的功能。事實上,我們還可以這么用:

var persons = new [] { new Person("Tom", 10), new Person("Jerry", 8) };XElement xml2 =     b.persons(        from p in persons        select b.person(p.Name, age: p.Age));

  XmlMarkupBuilder對LINQ的直接支持得益于XElement無與倫比的“包容性”(因此我認(rèn)為LINQ to XML其實只是LINQ to Object + 類庫)。至于age: 10這樣的代碼,其實是使用了C# 4.0的新特性:命名參數(shù)(Named Parameters)——C#還真把什么都為我們準(zhǔn)備好了。

  即便是大部分DynamicObject的示例都喜歡拿XML操作開涮(但還是沒有出現(xiàn)我這篇的用法,所以我還是“原創(chuàng)”),但事實上這個功能可發(fā)揮的余地非常之大。例如,陳貓同學(xué)提到他想用這個功能來簡化Silverlight中的JSON操作,剛“喜得貴女”的Phil Haack同學(xué)在上個月也提到一個設(shè)想,它在ASP.NET MVC中使用dynamic關(guān)鍵字來修飾View的Model,這樣在訪問Model的屬性時變可附加一些約定好的操作。例如,Model.Content表示讀取Content屬性的內(nèi)容,而Model._Content則表示在讀取Content之后自動進(jìn)行HTML編碼。這無疑簡化了我們的開發(fā)——當(dāng)然,強(qiáng)類型的各種優(yōu)勢就不復(fù)存在了。

  而這個功能對我的意義在于,我又找到了一種設(shè)計API的方式,它可以使類庫變得簡單好用——就好比上面的XmlMarkupBuilder一樣。雖然,這個示例的功能非常簡單,但是這也足以證明C# 4.0中的dynamic特性并不僅僅是“方便Interop操作”或是“簡化反射”這么簡單,如果我們可以發(fā)揮想象能力,加以充分利用同時又不濫用,我們的程序開發(fā)生活就會變得越來越美好。

  最后……我還是承認(rèn)了吧,這篇文章其實是標(biāo)題黨,真正Ruby Markup Builder功能非常強(qiáng)大而復(fù)雜,我們的XmlMarkupBuilder類只能算是冰山一角而已。

NET技術(shù)二十行C#代碼打造Ruby Markup Builder,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 精品一区二区三区免费观看 | 77se77亚洲欧美在线大屁股 | 91福利免费体验区观看区 | 亚洲二区在线观看 | 国产高清福利91成人 | 青青草伊人久久 | 992tv又爽又黄的免费视频 | 视频一区 在线 | 三级欧美 | 美女福利视频一区二区 | 韩国一大片a毛片女同 | 久久精品国产亚洲网站 | 看一级毛片国产一级毛片 | 日韩一区二区三区免费视频 | 狠狠干2023 | 国产午夜一级鲁丝片 | 被公侵犯肉体中文字幕一区二区 | 免费亚洲网站 | 国产成人精品日本亚洲直接 | 韩国一级做a爰片性色毛片 韩国一区二区三区 | 欧洲色综合 | 久久福利免费视频 | 夜色福利院在线看青草一 | 四虎影视永久在线 yin56xyz | 在线观看91 | 视频在线观看一区二区 | 大香网伊人久久综合观看 | 国产成人综合亚洲亚洲欧美 | 久久香蕉热| 91久久综合 | 欧美日在线观看 | 九九精品在线播放 | 一区二区三区四区精品视频 | 色多多视频在线 | 亚洲天堂一区二区三区四区 | 亚洲乱人伦精品图片 | 亚洲女人影院想要爱 | 欧美日韩一区二区三 | 亚洲视频一区在线观看 | 成年人免费在线视频观看 | 女的毛片毛片毛毛片毛毛毛毛片 |