适用于:Microsoft Visual Studio .NET
要求:本下载资料要求安装 Microsoft .NET Framework 1.1。
摘要:了解类型化数据集和 xsd.exe 工具所生成的类之间的区别,以及如何通过重用支持该代码生成过程的基础结构类来扩展这一过程,同时保持与 XMLSerializer 的兼容性。(23 页打印页)
内容
本页内容
简介
基础类
扩展 XSD 处理
XMLSerializer 的内部原理
通过 CodeDom 自定义
映射技巧
小结
简介
自动代码生成 — 无论是数据访问层、业务实体类还是用户界面 — 可以大大提高开发人员的生产效率。这一生成过程可以基于许多输入,例如数据库、任意 XML 文件、UML 关系图等。Microsoft?Visual Studio?.NET 随附了对从 W3C XML 架构文件 (XSD) 进行代码生成的内置支持,分为两种形式:类型化数据集以及与 XMLSerializer 配合使用的自定义类。
XSD 文件描述了允许包含在 XML 文档中以便被该文档视为有效的内容。由于需要以类型安全的方式对数据进行处理(这些数据最终将被序列化为 XML 数据以供使用),因此产生了各种将 XSD 转换为类的方法。我们可以回想一下,XSD 并“不是”作为一种描述对象及其关系的手段而创建的。已经存在一种更好的格式可用于该目的,它就是 UML,并且已被广泛用来对应用程序进行建模以及根据模型生成代码。因此,在 .NET 及其面向对象的编程 (OOP) 概念以及 XSD 的概念之间存在某些(预料的)不匹配现象。当您将 XSD 映射到类时,请记住这一点。
也就是说,可以将 CLR 类型系统视为 XSD 的子集:它支持一些无法映射到常规 OO 概念的功能。因此,如果您只是使用 XSD 来对类进行建模,而不是对文档进行建模,您很可能找不到任何冲突。
在本文的其余部分,我们将讨论类型化数据集方法,还将讨论通过 xsd.exe 工具生成的自定义类如何有助于得到更好的解决方案,以及如何扩展和自定义从 XSD 到类的生成过程的输出。
为了最深入地领会本文的内容,您需要对 CodeDom 有一些基本的了解。
类型化数据集有什么问题?
类型化数据集正在越来越多地用于表示业务实体,也就是说,用于充当应用程序各个层之间的实体数据传送器,甚至充当 Web 服务的输出。与“正常的”数据集不同,类型化数据集很有吸引力,因为您还可以获得对表、行、列等的类型化访问。然而,它们并非没有代价和/或限制:
• 实现开销:数据集包含许多可能不为您的实体所需的功能,如更改跟踪、类似于 SQL 的查询、数据视图、大量事件等等。
• 性能:与 XML 之间的序列化速度不够快。XMLSerializer 的性能很容易超过它。
• 互操作性:对于返回类型化数据集的 Web 服务的非 .NET 客户端而言,可能难以解决。
• XML 结构:许多分层的(而且完全有效的)文档及其架构无法扁平化为表模型。
获取有关类型化数据集的更多信息。
因此,除非数据集的其他功能普遍对您有用,否则使用类型化数据集进行数据传递可能不是最佳选择。值得庆幸的是,还有另一个可以利用的选择。
XMLSerializer 和自定义类
XMLSerializer 改善了 XML 数据处理方法。通过序列化特性,XMLSerializer 能够根据对象的 XML 表示形式还原对象,并且能够反序列化到 XML 形式。此外,它还能够以非常有效的方式完成这些工作,因为它可以生成动态编译的基于 XMLReader 的(因而也是流式的)类,该类专门用于序列化(以及反序列化)具体的类型。所以,它确实非常快捷。
阅读有关 XML 序列化特性的更多内容。
当然,猜测使用哪些特性以便符合某个 XSD 绝对不是一件好玩的事情。为了解决这个问题,.NET SDK 随附了一个可以帮助您完成艰苦工作的实用工具:xsd.exe。它是一个命令行应用程序,能够根据 XSD 文件生成类型化数据集和自定义类。自定义类在生成后具有相应的 XML 序列化特性,因此在进行序列化时,可以保证完全忠实于架构。
阅读 Don Box 对 XSD 以及 CLR 映射和特性的介绍。
迄今为止,一切都很好。我们具有有效且快速的方法将 XML 转换为对象或者将对象转换为 XML,并且我们具有能够为我们生成类的工具。问题在于,我们有时希望得到与所生成的内容稍有不同的内容。例如,xsd.exe 所生成的类无法数据绑定到 Windows 窗体网格,因为它查找属性而不是公共字段来显示。我们可能希望在许多地方添加自己的自定义特性,将数组更改为类型化集合,等等。当然,我们在做这些事情的时候,应保证在序列化时能够与 XSD 兼容。
自定义 XSD 将明显改变所生成的类的形式。如果您只是期望将 PascalCaseIf 变成实际的 XML 标准以便使用 camelCase,那么我建议您三思而后行。MS 的一些即将问世的产品表明它们将要使用 PascalCase 来表示 XML,以便使它们更好地支持 .NET。
如果您需要进行更多的与上述自定义类似的自定义,您的选择是什么?人们几乎普遍认为 xsd.exe 是不可扩展的,并且没有办法对其进行自定义。这是不准确的,因为 .NET XML 团队实际上向我们提供了恰好可供该工具使用的类。您将需要自己动手使用 CodeDom 以便利用它们,但自定义程度只受到您需要的限制!
您可以在下列文章中阅读有关 CodeDom 的内容:
Generating and Compiling Source Code Dynamically in Multiple Languages
Generate .NET Code in Any Language Using CodeDOM
返回页首
基础类
一种从 XSD 生成代码的方法是以统一的方式对架构对象模型 (SOM) 进行简单的迭代,并直接根据该模型编写代码。这正是大量为克服 xsd.exe 工具局限而创建的代码生成器所采取的方法。不过,这需要付出相当大的努力以及编写大量的代码,因为我们应考虑 XSD 到 CLR 类型映射、XSD 类型继承、XML 序列化特性等问题。掌握 SOM 也不是一件轻而易举的事情。如果无须由我们自己来完成所有工作,而只需添加或修改 xsd.exe 工具的内置代码生成,难道不好吗?
正像我前面所说的,但与普遍看法不同的是,xsd.exe 用于生成输出的类就在 System.XML.Serialization 命名空间中并被声明为公共类,即使 xsd.exe 工具在某种程度上不允许进行任何类型的自定义。它们中的大多数确实未进行记载,但我将在这一部分中向您说明如何使用它们。请不要被 MSDN 帮助中的以下声明吓住:“[TheTopSecretClassName] 类型支持Microsoft? .NET 框架基础结构,并且不适合直接从您的代码中使用”。我将在不进行胡乱删改以及不采用任何反射代码的前提下使用它们。
一种比相当平常的 "StringBuilder.Append" 代码生成好得多的方法是利用 System.CodeDom 命名空间中的类,而这正是内置代码生成类(从现在开始简称为 codegen)所做的。通过 CodeDom 中包含的一些类,我们可以用一种与语言无关的方式,在所谓的 AST(抽象语法树)中表示几乎所有的编程构造。稍后,另一个类(代码生成器)可以对其进行解释并生成您期望的原始代码,例如Microsoft? Visual C# 或Microsoft? Visual