C# 4.0,dynamic新特性,XML。在.NET 4.0中开始可以自行设计一些API,开放了更多的发挥空间。本文介绍了通过一个自己的API实现Ruby写法构架XML的功能,对C# 4.0的dynamic特性给予了极高的评价。
Ruby语法的简练深为程序员们所喜爱,而写C#的往往要忍耐易用性很差的写法。不过由于.NET 4.0的到来,C# 4.0新增的dynamic功用开放了更多的自己规划API的挑选,这样就敞开了许多自在的编程路途。老赵在下面介绍了自己打造的一个Ruby Markup Builder,展现了其强壮的XML结构功用。
从.NET诞生之日起就有了XML类库,可是从运用上来说十分不便利。例如咱们需求结构一个XML文档时,运用DOM API就要这样搞:
- varxmlDoc=newXmlDocument();
- varrootEle=xmlDoc.CreateElement("persons");
- xmlDoc.AppendChild(rootEle);
- varperson1=xmlDoc.CreateElement("person");
- person1.InnerText="Tom";
- varperson1Age=xmlDoc.CreateAttribute("age");
- person1Age.Value="10";
- person1.Attributes.Append(person1Age);
- rootEle.AppendChild(person1);
- varperson2=xmlDoc.CreateElement("person");
- person2.InnerText="Jerry";
- varperson2Age=xmlDoc.CreateAttribute("age");
- person2Age.Value="8";
- person2.Attributes.Append(person2Age);
- rootEle.AppendChild(person2);
别看这么多行代码,但实际上它只结构了这么简略的一个XML:
- <persons>
- <personage="10">Tom</person>
- <personage="8">Jerry</person>
- </persons>
我供认,DOM API确实十分谨慎(如XmlDocument和XmlElement的归属联系),十分契合界说,也十分的面向目标,可是这易用性也真实太差了。记住在03仍是04年的时分,我为在为项目做一个修改XML文档的WinForm应用程序,其时也不像现在那么简略想到“偷闲”的法门,而VS 2003也不像VS 2005/2008那么好用,因而可谓做的劳心费心。这个状况在.NET 2.0中也没有得到改动,直到有一天,LINQ to XML随.NET 3.5横空出世,于是乎XML的日子一会儿变得夸姣了许多。例如上面的功用只需寥寥数行便能够完成:
- varxmlDoc=newXElement("persons",
- newXElement("person",
- "Tom",
- newXAttribute("age",10)),
- newXElement("person",
- "Jerry",
- newXAttribute("age",8)));
尽管LINQ to XML一直是所谓C# 3.0中LINQ特性的一部分,与LINQ to SQL,LINQ to Object及LINQ to……某个其他并排,但我始终以为LINQ to XML实则仍是LINQ to Object的一种特别办法,仅仅它用于操作XML罢了。它的一切都是System.Xml.Linq命名空间下相关类库(如XElement)在起作用,不关LINQ什么事情。XElement等相关类型大大简化了咱们的开发,与DOM API比较,无论是XML的结构仍是读取都简略了许多。不过俗话说得好:“不怕不识货,就怕货比货”,这样的API与Ruby Markup Builder比较仍是有显着距离。请看:
- builder=Builder::XmlMarkup.new
- xml=builder.persons{|b|
- b.person("Tom",:age=>"10")
- b.person("Jerry",:age=>"8")
- }
请看上面这段代码,它天然没有运用Ruby言语的规范上色办法。我上色的意图是体现这个结构办法中的“噪音”——也就是与XML内容无关的部分。从中能够发现,Ruby不愧是一种噪音较少的言语,假如您测验运用这个办法来调查C#中LINQ to XML的做法,就会发现两者之间确实有显着的距离。当然,假如运用VB.NET的XML Literal或许噪音也很少,可是在我看来,XML Literal在XML结构方面的体现有些罗嗦,例如它需求开发人员一起供给元素的开端标签和闭合标签,或许在IDE的协助下此类代码输入较为简略,可是代码仍是略显冗余。
可是咱们这些不幸的C#程序员莫非只要在一边眼馋的份吗?不见得,咱们也能够来“享用”一把:
- dynamicb=newXmlMarkupBuilder();
- XElementxml=
- b.persons(
- b.person("Tom",age:10),
- b.person("Jerry",age:8));
哇,这是什么,怎样代码那么简略。很显着,从dynamic关键字上能够看出,这是C# 4.0中新增的功用。您或许会想“本来.NET 4.0对XML又有增强了”……其实并非如此,这是咱们自己扩展的功用。不过这应该算是更好的音讯,由于这说明咱们已经有才能自行扩展,自行规划这样的API了——这可是“渔”,比“鱼”可要值钱多了。而完成这样的功用也只需求短短二十几行C#代码:
- publicclassXmlMarkupBuilder:DynamicObject
- {
- publicoverrideboolTryInvokeMember(InvokeMemberBinderbinder,object[]args,outobjectresult)
- {
- XElementxml=newXElement(binder.Name);
- varattrCount=binder.CallInfo.ArgumentNames.Count;
- varelementCount=args.Length-attrCount;
- for(inti=0;i<elementCount;i++)
- {
- xml.Add(args[i]);
- }
- for(vari=0;i<attrCount;i++)
- {
- varattrName=binder.CallInfo.ArgumentNames[i];
- if(attrName[0]=='@')attrName=attrName.Substring(1);
- xml.Add(newXAttribute(attrName,args[i+elementCount]));
- }
- result=xml;
- returntrue;
- }
- }
DynamicObject是个特别的目标,简略地说它的行为能够被“扩展”——是如动态言语般真实的扩展,而非静态的多态。当咱们运用dynamic润饰变量后,在它之上的办法调用会由编译器和DLR配合出不相同的行为。例如,咱们在调用一个办法的时分,DLR会先查看这个动态目标上是否存在契合这个签名的办法,存在则最好,不然便会调用TryInvokeMember来“履行”一个动态办法,而它的参数就是此次调用的悉数信息。这样的做法被称为“Method Missing”操作,事实上Ruby Markup Builder也是运用Ruby目标中的这个特性来完成“调用什么办法,便生成什么元素”的功用。事实上,咱们还能够这么用:
- varpersons=new[]{newPerson("Tom",10),newPerson("Jerry",8)};
- XElementxml2=
- b.persons(
- frompinpersons
- selectb.person(p.Name,age:p.Age));
XmlMarkupBuilder对LINQ的直接支撑得益于XElement无与伦比的“包容性”(因而我以为LINQ to XML其实仅仅LINQ to Object + 类库)。至于age: 10这样的代码,其实是运用了C# 4.0的新特性:命名参数(Named Parameters)——C#还真把什么都为咱们预备好了。
即就是大部分DynamicObject的示例都喜爱拿XML操作开涮(但仍是没有呈现我这篇的用法,所以我仍是“原创”),但事实上这个功用可发挥的地步十分之大。例如,陈猫同学说到他想用这个功用来简化Silverlight中的JSON操作,刚“喜得贵女”的Phil Haack同学在上个月也说到一个幻想,它在ASP.NET MVC中运用dynamic关键字来润饰View的Model,这样在拜访Model的特点时变可附加一些约定好的操作。例如,Model.Content表明读取Content特点的内容,而Model._Content则表明在读取Content之后主动进行HTML编码。这无疑简化了咱们的开发——当然,强类型的各种优势就不复存在了。
而这个功用对我的含义在于,我又找到了一种规划API的办法,它能够使类库变得简略好用——就好比上面的XmlMarkupBuilder相同。尽管,这个示例的功用十分简略,可是这也足以证明C# 4.0中的dynamic特性并不仅仅是“便利Interop操作”或是“简化反射”这么简略,假如咱们能够发挥幻想才能,加以充分利用一起又不乱用,咱们的程序开发日子就会变得越来越夸姣。
最终……我仍是供认了吧,这篇文章其实是标题党,真实Ruby Markup Builder功用十分强壮而杂乱,咱们的XmlMarkupBuilder类只能算是冰山一角罢了。
【修改引荐】
- 详解C# 4.0中的新目标ExpandoObject
- 介绍C# 4.0新特性dynamic
- C#前史回顾及C# 4.0新特性一览
- C# 4.0 Dynamic关键字全解析
- C# 4.0 的4个新特性
知优网 » 增强的XML?经过C# 4.0 dynamic享用Ruby写法之讨论