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结构功用。

增强的XML?经过C# 4.0 dynamic享用Ruby写法之讨论  C# dynamic 第1张

从.NET诞生之日起就有了XML类库,可是从运用上来说十分不便利。例如咱们需求结构一个XML文档时,运用DOM API就要这样搞:

  1. varxmlDoc=newXmlDocument();
  2. varrootEle=xmlDoc.CreateElement("persons");
  3. xmlDoc.AppendChild(rootEle);
  4. varperson1=xmlDoc.CreateElement("person");
  5. person1.InnerText="Tom";
  6. varperson1Age=xmlDoc.CreateAttribute("age");
  7. person1Age.Value="10";
  8. person1.Attributes.Append(person1Age);
  9. rootEle.AppendChild(person1);
  10. varperson2=xmlDoc.CreateElement("person");
  11. person2.InnerText="Jerry";
  12. varperson2Age=xmlDoc.CreateAttribute("age");
  13. person2Age.Value="8";
  14. person2.Attributes.Append(person2Age);
  15. rootEle.AppendChild(person2);

别看这么多行代码,但实际上它只结构了这么简略的一个XML:

  1. <persons>
  2. <personage="10">Tom</person>
  3. <personage="8">Jerry</person>
  4. </persons>

我供认,DOM API确实十分谨慎(如XmlDocument和XmlElement的归属联系),十分契合界说,也十分的面向目标,可是这易用性也真实太差了。记住在03仍是04年的时分,我为在为项目做一个修改XML文档的WinForm应用程序,其时也不像现在那么简略想到“偷闲”的法门,而VS 2003也不像VS 2005/2008那么好用,因而可谓做的劳心费心。这个状况在.NET 2.0中也没有得到改动,直到有一天,LINQ to XML随.NET 3.5横空出世,于是乎XML的日子一会儿变得夸姣了许多。例如上面的功用只需寥寥数行便能够完成:

  1. varxmlDoc=newXElement("persons",
  2. newXElement("person",
  3. "Tom",
  4. newXAttribute("age",10)),
  5. newXElement("person",
  6. "Jerry",
  7. 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比较仍是有显着距离。请看:

  1. builder=Builder::XmlMarkup.new
  2. xml=builder.persons{|b|
  3. b.person("Tom",:age=>"10")
  4. b.person("Jerry",:age=>"8")
  5. }

请看上面这段代码,它天然没有运用Ruby言语的规范上色办法。我上色的意图是体现这个结构办法中的“噪音”——也就是与XML内容无关的部分。从中能够发现,Ruby不愧是一种噪音较少的言语,假如您测验运用这个办法来调查C#中LINQ to XML的做法,就会发现两者之间确实有显着的距离。当然,假如运用VB.NET的XML Literal或许噪音也很少,可是在我看来,XML Literal在XML结构方面的体现有些罗嗦,例如它需求开发人员一起供给元素的开端标签和闭合标签,或许在IDE的协助下此类代码输入较为简略,可是代码仍是略显冗余。

可是咱们这些不幸的C#程序员莫非只要在一边眼馋的份吗?不见得,咱们也能够来“享用”一把:

  1. dynamicb=newXmlMarkupBuilder();
  2. XElementxml=
  3. b.persons(
  4. b.person("Tom",age:10),
  5. b.person("Jerry",age:8));

哇,这是什么,怎样代码那么简略。很显着,从dynamic关键字上能够看出,这是C# 4.0中新增的功用。您或许会想“本来.NET 4.0对XML又有增强了”……其实并非如此,这是咱们自己扩展的功用。不过这应该算是更好的音讯,由于这说明咱们已经有才能自行扩展,自行规划这样的API了——这可是“渔”,比“鱼”可要值钱多了。而完成这样的功用也只需求短短二十几行C#代码:

  1. publicclassXmlMarkupBuilder:DynamicObject
  2. {
  3. publicoverrideboolTryInvokeMember(InvokeMemberBinderbinder,object[]args,outobjectresult)
  4. {
  5. XElementxml=newXElement(binder.Name);
  6. varattrCount=binder.CallInfo.ArgumentNames.Count;
  7. varelementCount=args.Length-attrCount;
  8. for(inti=0;i<elementCount;i++)
  9. {
  10. xml.Add(args[i]);
  11. }
  12. for(vari=0;i<attrCount;i++)
  13. {
  14. varattrName=binder.CallInfo.ArgumentNames[i];
  15. if(attrName[0]=='@')attrName=attrName.Substring(1);
  16. xml.Add(newXAttribute(attrName,args[i+elementCount]));
  17. }
  18. result=xml;
  19. returntrue;
  20. }
  21. }

DynamicObject是个特别的目标,简略地说它的行为能够被“扩展”——是如动态言语般真实的扩展,而非静态的多态。当咱们运用dynamic润饰变量后,在它之上的办法调用会由编译器和DLR配合出不相同的行为。例如,咱们在调用一个办法的时分,DLR会先查看这个动态目标上是否存在契合这个签名的办法,存在则最好,不然便会调用TryInvokeMember来“履行”一个动态办法,而它的参数就是此次调用的悉数信息。这样的做法被称为“Method Missing”操作,事实上Ruby Markup Builder也是运用Ruby目标中的这个特性来完成“调用什么办法,便生成什么元素”的功用。事实上,咱们还能够这么用:

  1. varpersons=new[]{newPerson("Tom",10),newPerson("Jerry",8)};
  2. XElementxml2=
  3. b.persons(
  4. frompinpersons
  5. 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类只能算是冰山一角罢了。

【修改引荐】

  1. 详解C# 4.0中的新目标ExpandoObject
  2. 介绍C# 4.0新特性dynamic
  3. C#前史回顾及C# 4.0新特性一览
  4. C# 4.0 Dynamic关键字全解析
  5. C# 4.0 的4个新特性
转载请说明出处
知优网 » 增强的XML?经过C# 4.0 dynamic享用Ruby写法之讨论

发表评论

您需要后才能发表评论