科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件.NET 框架中的 XML:在 .NET 框架中使用 XML 架构执行代码生成 映射技巧

.NET 框架中的 XML:在 .NET 框架中使用 XML 架构执行代码生成 映射技巧

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

.NET 框架中的 XML:在 .NET 框架中使用 XML 架构执行代码生成 映射技巧

作者:Daniel Cazzulino 来源: Microsoft 开发人员网络 2007年10月26日

关键字: XML

  • 评论
  • 分享微博
  • 分享邮件

如果您要更深入地研究代码生成工具本身,或者希望更进一步地自定义架构处理,那么您或许会对下列与 codegen 类有关的高级问题感兴趣。如果您只是要开发扩展和操纵 CodeDom,则它们对您不会有多大价值,您可以跳过本部分而不会有任何问题。

我已经通过检索元素的 XmlTypeMapping 来处理这些元素;我尚未使用其任何属性,但如果您必须要找到与元素对应的 CodeTypeDeclaration,则可能需要使用这些属性。有关 XmlTypeMapping 属性及其含义的简短说明,请参阅 MSDN 文档。但是,该类用在许多方案中,如该文档中所示的 SoapReflectionImporter 映射导入。至于我所使用的 XmlSchemaImporter,我已经发现 XmlTypeMapping.TypeFullName 和 XmlTypeMapping.TypeName 对一个特定架构元素的设计具有不正确的行为:如果该元素在某个序列内部包含单个未绑定的子元素,则两者都将错误地假定子属性的类型。

因此,对于以下架构元素:

<xs:element name="pubs"> <xs:complexType> <xs:sequence> <xs:element name="publishers" type="Publisher" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> </xs:element>

XmlTypeMapping.TypeFullName 和 XmlTypeMapping.TypeName 都没有“pubs”值(这是将要生成的类型),而是具有值“Publisher[]”,这是其唯一属性的类型。如果该序列具有一个以上的元素,则一切都可以按预期方式工作。请注意,无论元素的类型是否为命名的全局类型,或者无论该元素本身是否为引用,这一(明显的)错误都适用。

除了类型映射以外,XmlSchemaImporter 还可以检索将应用于其成员(字段)的映射。这很有用,因为 XSD/CLR 类型映射(包括 XSD 自定义派生类型)将被解析,并且您可以确信它就是由 XmlSerializer 使用的那个映射。您可以按如下方式获得成员映射:

XmlMembersMapping mmap = importer.ImportMembersMapping( 
  element.QualifiedName );
int count = mmap.Count;
for (int i = 0; i < count; i++)
{
  XmlMemberMapping map = mmap[i];
  //You have now: 
  //  map.ElementName
  //  map.MemberName
  //  map.TypeFullName
  //  map.TypeName
}

XmlMemberMapping.TypeFullName 容纳命名空间限定的 CLR 类型,尽管 XmlMemberMapping.TypeName 具有 XSD 类型名。例如,对于 XSD 类型“xs:positiveInteger”的成员,前者将是“System.String”,而后者将是“positiveInteger”。如果您没有访问该成员映射检索的权限,则必须知道 XmlSerializer 所使用的所有 XSD 到 CLR 类型转换规则。请注意,这些规则不必与用于 XSD 验证和 DOM PSVI 的规则相同。

对于成员导入,有一个重要的警告(同样,明显是一个错误)。您不能重用 XmlSchemaImporter,否则将得到由导入代码在 XmlMembersMapping 构建时引发的 InvalidCastException。这可以通过每次使用导入程序的新实例来加以解决。

有了这些信息,您可以彻底更改类的外观,例如,重命名属性以使首字母变成大写,而不会对序列化基础结构产生危害。

当我讨论 codegen 类的基本原理时,我说过您只能为全局定义的元素检索(导入)映射;如果您创建自己的自定义特性以修改得到的类,则将只能够针对顶级元素检索和分析它们,因为您将只具有这些元素的映射。例如,假设您添加了一个 code:className 特性,该特性被某个扩展用来更改生成的类名:

<xs:schema xmlns:code="http://weblogs.asp.net/cazzu" ...> <xs:element name="pubs" code:className="PublishersData"> <xs:complexType> <xs:sequence> <xs:element name="publishers" code:className="Publishers"> <xs:complexType>

您将能够为 pubs 元素检索这些映射,但无法为 publishers 子元素检索这些映射。因此,对其进行处理将是不安全的,因为 codegen 类将来可能发生更改。如果不能控制映射,您就不能简单地假设相应的 CodeTypeDeclaration 将具有与该元素相同的名称(以便找到和更改它)。当然,您可以自行决定是否可以接受这种危险。

查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章