.NET 框架中的 XML:在 .NET 框架中使用 XML 架构执行代码生成[5]

[入库:2005年8月18日] [更新:2007年3月25日]

本文简介:选择自 dlt3e 的 blog

   new codeassignstatement(
   new codefieldreferenceexpression(
   new codethisreferenceexpression(), member.name ),
   new codeargumentreferenceexpression( "value" ) ) );
  
  最后,我们只需向该类型中添加新的属性:
  
  type.members.add( prop );
  }
  
  好了,先前的架构通过该工具生成以下代码:
  
  /// <remarks/> [system.xml.serialization.xmlrootattribute(namespace="", isnullable=false)] public class publisher { /// <remarks/> public string pub_id;
  
  向该架构添加相应的扩展以后:
  
  <xs:schema elementformdefault="qualified" xmlns="" xmlns:xs="http://www.w3.org/2001/xmlschema"> <xs:annotation> <xs:appinfo> <code xmlns="http://weblogs.asp.net/cazzu"> <extension type="xsdgenerator.extensions.fieldstopropertiesextension, xsdgenerator.customtool" /> </code> </xs:appinfo> </xs:annotation> ...
  
  该架构现在将生成:
  
  ///
  [system.xml.serialization.xmlrootattribute(namespace="", isnullable=false)]
  public class publisher
  {
   private string _pub_id;
   ///
   public string pub_id
   {
   get
   {
   return this._pub_id;
   }
   set
   {
   this._pub_id = value;
   }
   }
  
  使用集合而不是数组
  对于任何比较像样的读写(具有 get 和 set 属性)对象模型而言,要使其可供程序员方便地使用,它的多值属性都应该基于集合,而不是基于数组。这样做会使修改值和操纵对象图变得更为容易。通常的方法涉及到从 collectionbase 派生一个新的类型化集合类。
  
  在将更改提交给 codedom 之前,xmlserializer 支持必须对集合进行检查。在分析和反射要序列化的类型的类的内部深处,有一个名为 typescope 的内部类。typescope 负责确保生成序列化代码。它包含一个有趣的方法,名为 importtypedesc,该方法执行大多数检查工作并且为支持的类型生成信息。在这里,我们找到了对 ixmlserializable(它检查其成员中的安全特性)、数组(必须具有等于 1 的秩)、enums、xmlnode、xmlattribute 和 xmlelement 等的特殊支持。
  
  尤其是对集合而言,导入方法检查实现 icollection 的类型,该类型必须满足下列规则:
  
  • 必须具有一个 add 方法,该方法不是由该接口定义的,因为它通常是为该集合将要容纳的专用类型而创建的。
  
  • 不得通过该集合实现 idictionary。
  
  • 必须具有一个默认成员(即一个索引器)并且该成员具有一个类型为 system.int32 (c# int) 的参数。系统将在所有类型层次结构中搜索这样的成员。
  
  • 在 add、count 和索引器中不能有任何安全特性。
  
  
  在验证上述信息以后,生成的派生自 xmlserializationwriter 的专用类在为我们的类型编写 xml 输出时,将使用 count 属性进行迭代,而不使用基于数组的属性的 lenth:
  
  myassembly.mycollection a = (myassembly.mycollection)o.@collectionproperty;if (a != null) { for (int ia = 0; ia < a.count; ia++) { write10_mycollectionitem(@"mycollectionitem", @"http://weblogs.asp.net/cazzu/", ((myassembly.mycollectionitem)a[ia]), false, false); }}
请注意,在给定对索引器的上一次检查之后,对集合和数组的索引访问是相同的,所以此处没有进行更改。
  
  相应的派生自 xmlserializationreader 的类使用类型化的 add 方法来填充集合:
  
  myassembly.mycollection a_2 = (myassembly.mycollection)o.@collectionproperty;
  ...
  while (reader.nodetype != system.xml.xmlnodetype.endelement)
  {
   if (reader.nodetype == system.xml.xmlnodetype.element)
   {
   if (((object) reader.localname == (object)id8_mycollectionitem &&
   (object) reader.namespaceuri == (object)id9_httpweblogsaspnetcazzu))
   {
   if ((object)(a_2) == null)
   reader.skip();
   else
   a_2.add(read10_mycollectionitem(false, true));
   }
   ...
  
  上面显示的读方法返回集合所期望的适当类型:
  
  myassembly.mycollectionitem read1_mycollectionitem(bool isnullable,
   bool checktype)
  
  既然已经检验了 xmlserializer 能够支持和正确处理基于集合的属性,那么将所有数组更改为相应的强类型集合就是安全的。
  
  可以将这一新的扩展设计为在上一个扩展之前或之后运行。其中的差别是明显的,因为迭代将分别从字段更改到新的属性。为了使该扩展独立于上一个扩展,我将对其进行编码以针对字段工作。不过,请注意,如果将其配置为在 fieldstopropertiesextension“之后”运行,则该代码将是不正确的。
  
  让我们首先分析将生成自定义集合的方法。该集合应如下所示:
  
  public class publishercollection : collectionbase
  {
   public int add(publisher value)
   {
   return base.innerlist.add(value);
   }
   public publisher this[int idx]
   {
   get { return (publisher) base.innerlist[idx]; }
   set { base.innerlist[idx] = value; }
   }
  }
  
  用于生成该类型化集合的代码为:
  
  public codetypedeclaration getcollection( codetypereference fortype )

本文关键:.NET 框架中的 XML:在 .NET 框架中使用 XML 架构执行代码生成
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top