Team Architect Edition 应用程序设计器简介,第二部分
Tony Loton
LOTONtech Limited
摘要:实用简介:将学习应用程序设计器的重点从面向服务系统的设计转向实现。
下载 ApplicationDesignerExample.exe 文件。
注此文件与本系列第一部分提供的下载文件相同。为了您的方便起见,这里也提供了下载。

本页内容
![]() | 简介 |
![]() | 设计面向服务的应用程序 |
![]() | 介绍其他应用程序类型 |
![]() | 小结 |
简介
在本系列的第一部分,我向您介绍了应用程序设计器,并向您展示了如何使用它来设计一个面向服务的货币转换示例。
本文,我将向您展示如何使用 Visual Studio 2005 Team Architect 来实现分布式系统,然后我以论述如何在整体设计中整合某些其他应用程序类型(即,外部 Web 服务和外部数据库)作为本文的结束。
设计面向服务的应用程序
作出了整体应用程序设计规划之后,现在可以生成构成此设计的应用程序的主干实现。只需右键单击图表上的任何空白部分,然后选择 Implement All Applications 即可。
在这样做之前,我首先为各种应用程序设置了不同的实现语言,让事情变得更有趣。我依次单击每个应用程序,并使用 Properties 窗口设置语言属性,如下所示:
• | 用 Visual C# 实现 BureauDeChange |
• | 用 Visual Basic 实现 CurrencyConverter |
• | 用 Visual Basic 实现 DollarExchangeApp |
• | 用 Visual C# 实现 EuroExchangeApp |
完成这些更改之后,开始执行 Implement All Applications 功能,启动图 1 所示的对话框。我可以用它来确认每个应用程序的实现语言(如上所示)和应用程序模板(所有示例中的 Empty Web Site)是否正确。

图 1. 确认应用程序实现对话框
实现的应用程序的好处
对于每个实现的应用程序,都会在解决方案中创建一个项目。不仅创建了主干代码(如您对 UML 代码生成工具所期望的),而且还创建了每个作为 Web 页或 Web 服务运行的应用程序所必需的全部支持文件。如图 2 所示。

图 2. 解决方案资源管理器显示实现的应用程序
在图 2 中,我突出显示了 USDollarService.asmx 文件,这是因为我要向您展示,在右键单击该文件并选择 View in Browser 时会发生什么。
浏览器启动时使用的 URL 直接指向一个由 .asmx 文件引用的 Web 服务,它最初显示的是一个由该 Web 服务提供的所有操作的列表,如图 3 所示。

图 3. USDollarService Web 服务(所有操作)
注执行应用程序以后,Web 服务本身在 Visual Web Developer Web Server 中自动启动。
如果熟悉 Web 服务,您就不会对此图感到意外,您知道我可以通过为 HTML 窗体提供输入并检查 Web 响应,继续对每个操作进行测试。
但是此时测试操作没有什么用处,因为这些操作还没有完全实现,而这正是我在下面要做的事情。只是因为 Visual Studio 已经为 Web 服务生成了主干类,生成了 IIS 所需的支持文件,甚至已经启动了这些服务,这并不意味着这些服务正在做一些有用的事情。还有一些编码工作需要完成,但工作量并不大。
前端 Web 应用程序也是如此,我可以右键单击 .aspx 文件 (DollarExchangeApp.aspx) 并选择 View in Browser 来启动它们。结果得到一个空白页!
回头看一下图 2,您可能还会注意到有一个文件类型未被 IIS 认为是所必需的。我指的是 .sdm 文件或系统定义模型(System Definition Model,SDM)文档。SDM 为分布式系统设计器使用的基础元模型提供了基础。每个应用程序都有一个 .sdm 文件,这些文件以可由其他工具处理的 XML 格式描述应用程序的特性(例如,在使用部署设计器评估部署时)。在实现应用程序关系图中定义应用程序之后,便生成这些文件;或者在将外部实现的应用程序定义(例如,外部 Web 服务)添加到应用程序关系图后,生成这些文件。在大多数情况下,都可以安全地忽略它们。实际上,强烈建议您不要直接编辑这些文件。
尝试一下!
假定您已经重新创建了我的应用程序设计,或者从我提供的 ApplicationDesigner.ad 文件加载了该程序,那么您现在可以尝试着实现这些应用程序。使用相关的语言设置要实现的每个应用程序,然后右键单击此关系图的空白部分并选择 Implement All Applications。
您可能希望首先复制一份 ApplicationDesign.ad 文件,这是因为一旦您实现了该文件中的应用程序,如果不重新实现所有的定义,就无法将此关系图作为另一个解决方案中应用程序设计的基础。
编码实现
尽管我已经使用 Visual Studio 为所有的应用程序生成了主干实现,但这些实现此时还不具备任何有用的功能。然而,许多困难的工作已经完成,因此使这些应用程序端到端工作不需要使用很多额外的代码,至少对于演示是这样。
让我们来看一看这些应用程序中的每一个,然后浏览我添加到每个实现中以使其正常工作的额外代码。
BureauDeChange 实现
如果回顾一下图 2,您就会看到在 BureauDeChange 应用程序项目中列出的 ExchangeRateService.asmx 文件。该文件的内容和该 Web 服务的入口点如下所示:
<%@ webservice class="BureauDeChange.ExchangeRateService" language="c#" codebehind="~/Application_Code/ExchangeRateService.cs" %>
根据上面这段信息,我可以确定实现该服务的代码隐藏文件,并在解决方案资源管理器中定位到此文件,或者只需右键单击 .asmx 文件,然后从 Context 菜单选择 View Code。
以下清单显示在服务实现的起始阶段由 Visual Studio 生成的主干代码。请注意,其中包含我输入的注释,这些注释是本系列第一部分中的摘要信息的一部分。
namespace BureauDeChange { [System.Web.Services.WebServiceBinding(Name = "ExchangeRateService")] public class ExchangeRateService : System.Web.Services.WebService { /// /// 该操作提供 fromCurrency 和 toCurrency 之间的交易转换率。 /// /// 货币代码,如“USD”或“EUR”。 /// 货币代码,如“USD”或“EUR”。 [System.Web.Services.WebMethod(), System.Web.Services.Protocols.SoapDocumentMethod(Binding = "ExchangeRateService")] public double getExchangeRate(string fromCurrency, string toCurrency) { throw new System.NotImplementedException(); } } }
它包含在应该执行的 getExchangeRate 操作的方法体,所以我对此进行了修改,直接在 throw 语句前面加入了以下代码行:
if (fromCurrency.Equals("USD") && toCurrency.Equals("EUR")) return 0.78; if (fromCurrency.Equals("EUR") && toCurrency.Equals("USD")) return 1.28;
为了方便起见,我选择了保留 throw 语句作为该方法的最后一行,这样,对于任何尚未实现的货币转换,都会引发 NotImplementedException。根据实际情况,这意味着可以对英镑进行双向转换,如果您有兴趣,可以在尝试这个程序时添加此功能。
添加以上这些代码行并保存更改之后,我可以测试这个 Web 服务。因此,我右键单击 ExchangeRateService.asmx 文件,然后选择 View in Browser,此时会看到一个类似于图 3 的页面,只不过这次列出的是 ExchangeRateService 的 getExchangeRate 操作。
选择这个操作,进入图 4 所示的窗体,在调用此 Web 服务前,我可以使用该窗体为 fromCurrency 和 toCurrency 输入参数。

图 4. getExchangeRate Web 服务操作
这正是我由衷喜欢 Web 服务的一个原因 — 可以使用一个自动生成的 HTML 窗体对其进行测试,而不必首先实现一个真实的客户端。
图 5 给出了该 Web 操作调用的结果。快速回顾一下这段代码来确认这个结果 — 0.78,与我期望的完全相同。我可以重新测试该服务,方法是将“EUR”作为 fromCurrency 的参数,而将“USD”作为 toCurrency 的参数来产生结果 1.28。

图 5. getExchangeRateService 结果
按照我上面给出的步骤,您可以非常顺利地编写此实现的代码并对其进行测试。但是我建议,在我介绍完所有这些实现之后,您在这一部分的最后正式地尝试一次。
CurrencyConverter 实现
CurrencyConverter 应用程序提供两项 Web 服务。我将向您展示我如何完成 USDollarService 的实现,至于如何实现补充的 EuroService 需要您自己去领会。正如您将看到的,这并不是什么高深的火箭科学。
首先,我右键单击 USDollarService.asmx 文件,然后选择 View Code。Visual Studio 生成的主干代码如下所示:
Imports System.Web Imports System.Web.Services Imports System.Web.Services.Protocols Namespace CurrencyConverter <System.Web.Services.WebServiceBinding(Name:="USDollarService")> _ Public Class USDollarService Inherits System.Web.Services.WebService ''' <System.Web.Services.WebMethod()> _ <System.Web.Services.Protocols.SoapDocumentMethod(Binding:="USDollarService")> _ Public Function fromEuros(ByVal amount As Double) As Double End Function ''' <System.Web.Services.WebMethod()> _ <System.Web.Services.Protocols.SoapDocumentMethod(Binding:="USDollarService")> _ Public Function fromPoundsSterling(ByVal amount As Double) As Double End Function End Class End Namespace
为了完成 Web 服务的实现,我将几行代码输入到 Web 方法体中。如果是 fromEuros 方法,则所需的代码为:
Dim rate As Double Dim exchangeService As New CurrencyConverter.WebServiceProxies.ExchangeRateService rate = exchangeService.getExchangeRate("EUR", "USD") Return amount * rate
这段代码的作用是设置 BureauDeChange 应用程序提供的 ExchangeRateService 的一个代理,调用该服务的 getExchangeRate 操作,再将提供的金额(单位为欧元)与汇率相乘,然后以美元为单位返回金额。
注代理是一个本地对象,您可以将它作为远程 Web 服务本身(虽然它实际上不是)来调用。代理在内部发出适当的 SOAP 请求并对响应进行解包,而您无需了解它是如何工作的。实际上,代理从概念上填写了图 4 中的窗体并捕获如图 5 所示的响应。
一旦输入并保存了这段代码,我就能够测试由 CurrencyConverter 应用程序的 USDollarService 提供的 fromEuros 操作的实现,方式与我以前测试 BureauDeChange 应用程序的 ExchangeRateService 提供的 getExchangeRate 操作完全相同。只需在浏览器中查看 USDollarService.asmx 文件,选择 fromEuros 操作,然后填写一个类似于图 4 所示的 HTML 窗体,不过这次要求输入金额(单位为欧元)。
当我输入的金额为 100 欧元时,以美元为单位的响应如下所示:
<?xml version="1.0" encoding="utf-8" ?> <double xmlns="http://tempuri.org/">128</double>
DollarExchangeApp 实现
我现在要描述的 DollarExchangeApp 实现也可以用于演示 EuroExchangeApp 的实现,这几乎是完全相同的。在开始时,Visual Studio 将生成一个默认的 Web 页 — Default.aspx,其内容如下。
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="Default_aspx" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> </div> </form> </body> </html>
我使用 Web 窗体设计器构造应用程序的 UI,您可以提前看一看下面的图 6 以对此有一个感性认识。设计完窗体之后,下面的 HTML 代码会出现在上述清单的 <div> 和 </div> 标记之间:
<asp:Label ID="Label1" Runat="server" Text="Enter amount in Euros" Width="142px" Height="19px"></asp:Label> <asp:TextBox ID="euroAmount" Runat="server"></asp:TextBox> <asp:Button ID="convertButton" Runat="server" Text="Convert to US Dollars" OnClick="convertButton_Click" /> <br /> <asp:Label ID="Label2" Runat="server" Text="Amount in US Dollars is" Width="158px" Height="19px"> </asp:Label> <asp:TextBox ID="dollarAmount" Runat="server"></asp:TextBox>
当您亲自实现这个应用程序时,只需将这段代码粘贴到 Default.aspx 文件而不用自己重新设计该窗体。
除了 UI 代码之外,我还需要一个用于按钮的事件处理程序,因此我在窗体设计视图中双击此按钮,然后输入以下代码。
Protected Sub convertButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim dollarService As New DollarExchangeApp.WebServiceProxies.USDollarService dollarAmount.Text = dollarService.fromEuros(Double.Parse(euroAmount.Text)) End Sub
这段代码创建一个 USDollarService 的代理,并对它进行调用,调用方式与先前 USDollarService 调用 ExchangeRateService 所采用的方式相同。
从名为 euroAmount 的文本框中获得要从欧元转换为美元的金额,在带有 dollarAmount 标记的文本框中显示以美元为单位的结果金额。图 6 显示我测试该应用程序时发生的情况。

图 6. DollarExchangeApp
尝试一下!
现在,您可以按照上面的描述,尝试着完成 DollarExchangeApp 和补充的 EuroExchangeApp 的实现。如果您还未这样做,那么您首先需要完成其他 Web 服务应用程序的实现。
介绍其他应用程序类型
到现在为止,在本系列文章中,我已经演示了在一个包含相互连接的 Web 应用程序和 Web 服务的分布式系统的环境中,如何使用应用程序设计器。这是因为,应用程序设计器对 Web 服务设计的强有力支持使得设计 Web 应用程序只需要很少的额外工作。
当然,应用程序设计器还可以用于设计很多其他类型的应用程序(例如,数据库应用程序、BizTalk 服务应用程序、Windows 和 Office 应用程序,等等)。因此,如果连某些可用于设计分布式系统的其他应用程序原型都没有提及,就无法完整地涵盖应用程序设计器。现在,我要选取其他两种应用程序类型(外部 Web 服务和外部数据库),并且将针对每种类型展示如何将其合并到我的设计中。
ExternalWebService
在我首次介绍我的分布式系统的整体设计时,我曾提示,在实际应用中,BureauDeChange 应用程序可能由第三方提供。事实上,只要他们都赞同 ExchangeRateService 的定义,就可以有多家第三方组织提供同样的服务,而我就可以连接到能够提供最佳汇率的服务。
假定至少有一家第三方供应商。要连接到它的服务,我只需从工具箱拖出一个 ExternalWebService 原型,然后将 Web 服务的 URL 输入到对话框中,如图 7 所示。

图 7. 添加 Web 引用
在该示例中,我利用了下面的事实:我已经让一个 ExchangeRateService Web 服务从我先前的实现示例中运行,因此我使用了该服务的 URL,就好像它是由第三方供应商提供的一样。一旦单击了 Add Reference 按钮,系统就会向我的关系图添加一个名为 ExchangeRateService 的新 Web 服务提供程序终结点,该终结点附加到一个具有相同名称的新应用程序中,如图 8 所示。

图 8. 带有外部 Web 服务的应用程序设计
除了应用程序名称上的不同之外,从客户端的角度来看,该外部 Web 服务的 ExchangeRateService 与我本人实现的 BureauDeChange 应用程序的 ExchangeRateService 是等效的。因此,我以同样的方式将其连接到 CurrencyConverter。
ExternalDatabase
无论我是亲自实现 ExchangeRateService,还是依赖第三方供应商实现 ExchangeRateService,最终该服务都会从数据库获取其汇率信息。
使用我自己的实现,我可以通过从工具箱中拖出一个 ExternalDatabase 原型,从而在应用程序关系图中展示这一点。在图 9 中,我就是这样做的,并在将数据库连接到 BureauDeChange 应用程序之前将其重命名为 ExchangeRates。

图 9. 带有 ExternalDatabase 的应用程序设计
将数据库连接到客户端应用程序时,Visual Studio 提示输入数据源。此时,您可以选择简单地取消输入数据源,从而推迟定义数据源,或者以后连接到数据源。当然,我正期待着这个对话框,因此我预先创建了一个 SQL Server 数据库来充当该数据源。要这样做,可以在 Server Explorer 中右键单击 Data Connections 项,然后选择 Create New SQL Server 数据库。
图 10 和 图 11 显示为了完成示例数据库连接而输入的详细信息。

图 10. 选择数据源

图 11. 连接属性
小结
应用程序设计器如同 Team Architect 拼图中的一块。就其自身而言,它非常有用的一点是,作为一种设计应用程序的方式,它只需少量的工作即可实现这些应用程序。但是为了从这个可视化设计器中获取最大价值,应将其放入其他设计器的环境中,这一点非常重要。在我的后续文章中,将演示使用系统设计器来设计由应用程序组成的可部署系统的下一个逻辑步骤。
Tony Loton 是一位 Microsoft 认证专家 (MCP),他身兼数职,如 LOTONtech Limited 的首席顾问/主管、Cogenture 的 Microsoft 实践首席顾问/首脑,以及英国 Open University 的助理讲师。他目前正在与人合著 Professional Visual Studio 2005 Team System (ISBN 0764584367) 一书,该书将于 2005 年夏由 Wiley/Wrox 出版。