65.9K
CodeProject 正在变化。 阅读更多。
Home

SmartCodeGenerator – 使用 XML 驱动代码生成。使用 ASP.NET 转换 XML 而不是 XSLT。

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.81/5 (9投票s)

2007年4月26日

CPOL

9分钟阅读

viewsIcon

58660

downloadIcon

435

本文介绍了如何使用 XML 驱动代码生成。逐步展示了如何从 XSD 生成强类型对象。ASP.NET 开发人员也可以将本文作为参考,了解如何使用 ASP.NET 而不是 XSLT 转换 XML。

摘要

本文介绍了如何将 XML 用作 SCG 模板的元数据源。它还逐步展示了如何从 XSD 生成强类型对象,并在模板中使用它们来生成基于文本的输出。ASP.NET 开发人员也可以将本文作为参考,使用 ASP.NET 脚本转换 XML 并避免使用 XSLT。

Screenshot - image001.jpg

SmartCodeGenerator

SmartCodeGenerator (SCG) 是一个 ASP.NET 2.0 网站或一个 ASP.NET 1.1 Web 应用程序,它是一个功能齐全的基于模板的代码生成器,允许您生成任何文本语言的代码。模板使用任何 ASP.NET IDE(例如 Visual Studio)编写,作为 ASP.NET 用户控件。

SmartCodeGenerator 的当前功能列表包括

  • SCG 项目是一个 ASP.NET Web 项目,它使用现有的 ASP.NET 2.0 或 ASP.NET 1.1 Web 应用程序概念
  • 所有开发都可以在 VS2005 或 VS2003 中完成
  • SCG 项目可以在 Cassini Web 服务器上运行
  • SCG 项目可以使用 NAnt 构建和运行
  • 在模板中使用 XML 元数据。
  • 可扩展的模板生成引擎
  • 用于 MSSQL、Oracle 和 MySQL 的开源数据库模式发现 API
  • 生成基于文本的输出
  • 以批处理模式生成输出
  • 完全可定制的基于模板的代码生成
  • 记住自定义属性数据条目
  • Intellisense、编译、调试、代码片段、源代码视图、设计视图以及 Visual Studio IDE 提供的所有其他无数功能
有关最新下载,请参阅 Codeplex。本文基于 CTP 2.7,并尝试回答如何使用 SmartCodeGenerator 根据 XML 元数据生成输出。有关 SCG 框架的架构概述和使用概述,请参阅 Code Project 上的以下三篇文章:

SmartCodeGenerator - Visual Studio 和 ASP.NET 代码生成体验 - 架构概述”。

SmartCodeGenerator - Visual Studio 和 ASP.NET 代码生成体验 - 使用概述”。

“SmartCodeGenerator - ASP.NET、NAnt 和 Cassini 的代码生成体验”

引言

我们都同意 XML 的主要目的是促进不同系统之间的数据共享。但是,相同的 XML 也可以用作模板生成工具的强大输入。CodeSmith 的粉丝可能已经熟悉 XmlProperty,并且已经在各种示例中看到过。在本文中,我将说明如何使用 XML 作为 SCG 模板的元数据源。XML 提供了一种基于文本的方法来描述信息并对其应用基于树的结构,而 SCG 则促进使用您喜欢的 .NET 语言(C#、Vb.Net 等)编写逻辑和代码。通过结合这两种技术,我们可以为以前非常复杂的系统生成有意义的输入和输出。在代码生成领域,XML 现在被大量用作元数据源,用于生成业务对象、数据访问层甚至用户界面。另一种做法是根据数据库结构生成不同的应用程序层,但 XML 越来越受欢迎,因为它在将逻辑作为模板的元数据源集成方面提供了更大的灵活性。例如,在这个示例中,我定义了类名及其属性,并指定生成一个带有网格视图组件和分页支持的 UI。请注意,这在数据库结构中定义会有点混乱。

  <?xml version="1.0" encoding="utf-8" ?>
  <BusinessObjects xmlns="http://www.smartcodegenerator.com">
    <class name="Student">
      <properties>
        <property name="Id" type="String" maxSize="36" />
        <property name="Name" type="String" maxSize="96" />        
      </properties>
      <userinterface generate="true">
        <uicomponent>GridView</uicomponent>
        <gridview paging ="true" rownum="20">          
        </gridview>
      </userinterface>
    </class>    
  </BusinessObjects>


让我们看看如何在 SCG 模板中使用 XML。

如何在 SCG 模板中使用 XML 元数据?

为了解释这项技术,我将使用一个简单的例子从 XML 生成 HTML,然后来看一个更有用的例子,我们将以 XML 格式定义业务对象,然后使用 SCG 生成对象层、数据访问层、多个表和存储过程。

步骤 1:定义您的 XML 模式并生成 XSD

让我们以这个示例 XML students.xml 为例,其中存储了学生相关数据,如 id、姓名、课程等。

<Students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
  <Student>
    <ID>2</ID>
    <FirstName>Chris</FirstName>
    <LastName>Heale</LastName>
    <Courses>
      <Course>
        <ID>1</ID>
        <CourseName>Programming1</CourseName>
      </Course>
      <Course>
        <ID>2</ID>
        <CourseName>Programming2</CourseName>
      </Course>
    </Courses>
  </Student>
</Students>


当我们已经定义好将用作模板元数据的 XML 后,我们要做的第一件事是从该 XML 文件创建 XSD(XML 模式)。我们可以通过 Visual Studio 附带的命令行工具 xsd.exe 来完成此操作。以下命令将为您生成一个 xsd。

C:\Temp>xsd students.xml
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'C:\Temp\students.xsd'.

另一种方法是使用 Visual Studio。在 Visual Studio 2005 中打开所需的 XML 文件,然后按 XML>创建架构。



这将自动创建 xsd 架构,您也可以在设计器中查看/修改该架构。




步骤 2:从 XSD 生成强类型对象

一旦我们有了模式文件,我们就可以从 xsd 生成 .NET 类了。您可以通过多种方式实现此目的。其中一些方法可能是

  • a. 通过使用 Visual Studio 附带的 xsd.exe。
  • b. 通过下载免费的 Visual Studio 插件 xsdObjectGen。
  • c. 通过使用本文源代码中提供的 scgxsd_console.exe。

以下命令将以您首选的语言生成 .NET 类。

C:\Temp>xsd students.xsd /l:cs /c
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'C:\Temp\students.cs'.

有关 xsd.exe 命令行选项的完整列表,请参阅此链接
http://msdn2.microsoft.com/en-us/library/x6c1kb0s(vs.71).aspx

我将在本文后面更详细地介绍 scgxsd_console.exe。

步骤 3:在 SCG 项目中添加生成的类

只需将生成的 students.cs 添加到您的 SCG 项目中。它可能看起来像这样




现在我们准备在 Visual Studio 中编写我们的 SCG 模板,并获得 XML 对象的完整智能感知支持。

步骤 4:编写 SCG 模板

我只是在“TheProperties.cs”中定义了 Students 的一个属性,并且有一个 XML 模式的强类型表示,可以在我的模板中随时使用。

private Students studs; 
public Students Studs 
{ 
  get 
  { return studs; } 
  set { studs = value; } 
} 





请注意,当我们编写 SCG 模板(一个 ASP.NET 用户控件)时,我们拥有完整的智能感知支持。ASP.NET 开发人员也可以使用这种技术将 XML 转换为所需的格式,并避免使用 XSLT。有关更多详细信息,请查看我的博客文章:“使用 ASP.NET 脚本代替 XSLT 的替代方法”。

步骤 5:读取 XML 并生成输出

一旦您对 SCG 模板满意,您就可以指向任何符合您定义的 xsd 模式的 XML 文件并生成输出。本文提供的示例使用以下模板生成 HTML 输出。
<html>
<body>
<h1>Number of Students <%=Studs.Student.Length%></h1>
<h2>Report Date: <%= DateTime.Now %></h2>
<table border="1" cellpadding="1" cellspacing="1">
<tr><th>#</th><th>
    Student</th><th>
    Course</th></tr>
<% for (int i = 0; i < Studs.Student.Length; i++) 
   { %>   
<tr>
<td><%=i%></td>
<td><%= string.Format("{0} {1}",
Studs.Student[i].FirstName, Studs.Student[i].LastName)%></td>
<% for (int j = 0; j < Studs.Student[i].Courses.Length; j++) 
   { 
       if (j==0)
       {%>
   
<td><%= Studs.Student[i].Courses[j].CourseName %></td>
<%}
       else{%>
       <tr><td></td><td></td>
<td><%= Studs.Student[i].Courses[j].CourseName %></td></tr>
       <%} %>
<% } %>
</tr>
<% } %>
</table>
</body>
</html>

生成的输出如下:

scgxsd_console.exe

scgxsd_console.exe 也从 XSD 模式生成 .Net 类。您会很高兴知道 .Net Framework 带有丰富的库,支持用几行代码从 XSD 生成 .Net 类,Mike Hadlow 在他的博客文章“编写自己的 xsd.exe”中展示了其中的技巧。我同样编写了 scgxsd_console.exe,也用 Reflector 对 xsd.exe 做了一些调整,它们使用的代码大致相同。从高层次来看,xsd 到 .Net 类的创建过程如下:

a. 将您的 xsd 文件加载到 XmlSchema 中。

XmlSchema xsd = XmlSchema.Read(stream, null);

b. 创建一个引用您的模式的 XmlSchemaImporter 实例。此类用于生成从 XSD 类型到 .net 类型的映射。

XmlSchemaImporter schemaImporter = new XmlSchemaImporter(xsds); 

c. 创建一个 CodeDom CodeNamespace 实例,您将在其中构建 .net 类型的语法结构。
CodeNamespace codeNamespace = new CodeNamespace("SmartCodeGen"); 

d. 创建一个 XmlCodeExporter 实例,引用您用于导出类型的 CodeNamespace。此类实际上在 CodeNamespace 中创建 .net 类型的语法结构。
XmlCodeExporter codeExporter = new XmlCodeExporter(codeNamespace); 

e. 为您希望从 XSD 导出的每种类型创建一个 XmlTypeMapping 实例。
Listmaps = new List(); 
foreach(XmlSchemaType schemaType in xsd.SchemaTypes.Values) 
{ 
  maps.Add(schemaImporter.ImportSchemaType(schemaType.QualifiedName)); 
} 
foreach(XmlSchemaElement schemaElement in xsd.Elements.Values) 
{ 
  maps.Add(schemaImporter.ImportTypeMapping(schemaElement.QualifiedName)); 
} 

对每个 XmlTypeMapping 对象调用 XmlCodeExporter 上的 ExportTypeMapping 方法,这将在 CodeNamespace 对象中创建类型语法。

foreach(XmlTypeMapping map in maps) 
{ 
  codeExporter.ExportTypeMapping(map); 
}

我使用 CSharpCodeProvider 为在 CodeNamespace 对象中创建的类型输出 C# 源代码。但是您也可以通过添加对 Microsoft.VisualBasic 的引用来使用 VBCodeProvider。

CSharpCodeProvider codeProvider = new CSharpCodeProvider(); 
using(StringWriter writer = new StringWriter()) 
{ 
  codeProvider.GenerateCodeFromNamespace(codeNamespace, writer, new 
  CodeGeneratorOptions()); 
  string s = (writer.GetStringBuilder().ToString()); 

  using (StreamWriter sw = File.CreateText(_filename)) 
  { 
    sw.Write(s); 
  } 
} 

本文附带了上面描述的完整源代码。

下面是使用“scgxsd_console.exe”生成 .Net 类的一个示例。以下命令从 students.xsd 读取并生成 students.cs

scgxsd_console c:\students.xsd c:\students.cs


使用 SmartCodeGenerator 生成业务对象

在浏览互联网时,我发现了 JR Hull 撰写的文章“CodeSmith 的业务对象”。其中包含一些 CodeSmith 模板,这些模板从 XML 中定义的架构生成对象层、数据访问层和相关 SQL。我认为这将是一个很好的快速示例,可以展示当 XML 转换为与 SCG 一起使用时,它会产生相同的输出。这些 SCG 模板也可以随本文的源代码一起下载。请注意,Hull 编写的模板没有使用 CodeSmith 的 XmlProperty,他更喜欢使用 XmlDocument、XmlNodeList、XmlNode 对象。我也使用了相同的方法,这演示了在 SCG 模板中检索和使用 XML 数据的另一种方式。唯一需要关注的是,如果以这种方式编写代码,在开发过程中将无法获得 XML 模式的智能感知支持,这我在第一个示例中已经描述过。我必须补充的另一点是,我故意保持 JR Hull 的模板不变,以演示将 CodeSmith 模板轻松移植到 SCG 模板的便利性。

以下是使用 XmlNodeList、XmlNode、XmlNode.Attributes 等的 SCGTemplate 的一个小快照。

<ItemGroup>
    <Compile Include="BusinessLogic\BaseObjectClass.cs" />
    <Compile Include="DataAccess\BaseDataClass.cs" />    
    <%foreach (System.Xml.XmlNode classNode in ClassList)
      { 
          TheTargetClass = classNode.Attributes["name"].Value;%>
    <Compile Include="BusinessLogic\<%=TheTargetClass%>.cs" />
    <Compile Include="BusinessLogic\<%=TheTargetClass%>Collection.cs" />
    <Compile Include="DataAccess\<%=TheTargetClass%>Data.cs" />   <%} %>    
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
  <%foreach (System.Xml.XmlNode classNode in ClassList)
      { 
          TheTargetClass = classNode.Attributes["name"].Value;%>
    <Content Include="SQL\<%=TheTargetClass %>.sql" /><%}%>
  </ItemGroup>

以下是运行中项目的快照。

结论

SCG 是一个非常强大的基于 100% ASP.NET 的代码生成框架,在本文中,我演示了如何使用 XML 作为元数据源来生成模板。然而,本文也可以作为 ASP.NET 开发人员的参考,他们希望使用 ASP.NET 脚本转换 XML。结合两种强大的技术,XML 和 ASP.NET 脚本,打开了许多其他可能性的大门。我在这篇文章中没有涉及 XLinq,这也是一个非常有趣的主题。SCG 能做的远不止这些,所以请给我您的反馈,让我知道您还希望在 SCG 中看到哪些其他功能。

感谢您一直以来的陪伴,请加入社区并分享您的 SCGTemplates 和 UIProperties。

校对由 Christopher Heale 完成。
© . All rights reserved.