扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者: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领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者