Tony Loton LOTONtech Limited
2005年3月
摘要:学习如何使用Visual Studio 2005 类设计器来设计及用图表示API。(18页)
![*](http://img.microsoft.com/library/gallery/templates/MNP2.Common/images/3squares.gif)
本页内容
![]() | 介绍 |
![]() | 类分析 |
![]() | 类设计 |
![]() | 流通转换API |
![]() | 流通转换Web服务 |
![]() | 结论 |
介绍
在本文中,我将介绍类设计器,在Visual Studio 2005中(除了Express 版)一个新的图形化的设计工具。类设计器不是一个新的分布式系统设计工具,但它有一些相似之处和一些补充。
图 1显示了类设计器是如何根据它与应用程序设计器的关系被画到一张大图当中的。
![vstsclassdesigner-fig1.gif](https://i-blog.csdnimg.cn/blog_migrate/e4309e86d03fd80a8e069413520056a3.png)
图 1. 类设计器与应用程序设计器的关系
在 之前的指导中,在应用程序设计器中确定的解决方案结构-做为一个项目-在你通过类设计器中设计的类的应用程序定义能够被定位。在之后的指导中,类设计使用 类设计器能够变为通过使用应用程序设计器设计的程序服务提供的参数或返回类型。这听起来像鸡和鸡蛋的关系,但你可以使用标准语言类型(如double, int和string)设计应用程序服务,并且之后可以翻新适当的设计类;或者你能够设计类最初做为一个标准独立的类库而优先于应用程序模型。在本文中, 我将演示这些方法。
在你获得错误的想法前,让我强调我描述的应用程序设计器和类设计器的相互关系。完全在你的程序中使用类设计器不是必需的,也不是很完美的。事实上,如果你不运行Visual Studio 2005 Team Architect Edition,对你只是可选的。
这个设计器被命名为类设计器,因为主要被用于设计类库和API。这个名字与统一建模语言(UML)术语是一致的。但是,类声明仅是在类图表,枚举,构造,接口和委派中能够被声明类型中的一个。
在这篇文章中,我将经常讨论托拽类到类图中,删除类等。做为一般规则,无论何时我都使用术语类,对类,接口,枚举,委派或构造而言能够很快被记住。什么地方不是这种情况,我将特别指出。
首 先,我将为我选择的区域提供一个分析(类)模型。我将通过展开它到设计模型中做为一个执行的基本,来定位这个模型中的一些限制。最终设计模型是独立的,而 不会建立一个API,因为对功能而言它事实上不会做任何事。,因此我将为API自身设计一个附加的类。最后,我将在这篇文章中关联这些工作以及在我之前的 应用程序设计器文章中设想的应用程序设计。
无论在哪我演示的代码都相当于图示的类,代码将会使用C#符号来声明。因为.NET设计的风格无论你选择哪种语言都十分漂亮,因此我使用的示例的简单代码即使你使用Visual Basic .NET 程序也可以。
事 实上,我能够通过在Visual Basic中在我提示你建立一个C#类库时建立一个VB类库,来重演我的步骤。你注意仅有的不同是一些细小的技术不同点反映了你使用语言的不同。不像 UML一体适用的方法,在你使用Visual Basic类时使用Visual Basic术语(像公共的,友好的),在使用C#类时,类设计器使用C#术语 (像公共的,受保护的)。
类分析
在我之前的文章中,介绍应用程序设计器,我设想了一个Web服务,ExchangeRateService,,它的目的是提供最近的在两个指定流通中交换的速率。我也设想了一个分开的Web服务,允许一些指定在一个流通被修改到另一个流通中。在此我也将在示例上画出图,但我不会强制你重新去看之前的那篇文章。
因 此,什么是这些Web服务的错误呢?它们工作中什么都没有,除了它们的有效性通过事实被限制,每个服务返回一个单一的值-交换速率或转换数量,分别地-做 为一个double值。对于一次性转化很好,但如果我想保留fromAmount,toAmount,数据/时间,转换速率,有关的两个流通的历史记录就 没有用了。
为了帮助你形象化这个概念,我勾画了一幅图(图2)来显示我的想法。
![vstsclassdesigner-fig2](https://i-blog.csdnimg.cn/blog_migrate/f02c34d06d506f7a01db3007902f1b48.png)
图 2. 流通交换分析实体
一个增强的ExchangeRateService,优于返回一个double值,将返回一个ExchangeRate实体保持数据时间,速率(交换的),fromCurrency (代码),和toCurrency (代码),速率是可用的。这些都显示在了图2的右侧。
一个增强的CurrencyConverterService,由于返回一个double值,将返回一个ExchangeTransaction实体保持转化的fromAmount和toAmount。这些显示在了图2的左侧。
我使用这些点的词实体来强调在我想法中第一个删掉的分析或区域,模型。在正当的过程中,我将提炼这些实体到一个设计模型中,指出实体将变为类和其它类型,如枚举。
注意:如果你继续看,你将看到CurrencyCode已经标记为一个枚举;就像一个使用Visual Studio 2005类设计器画出这些分析模型的结果。这个阶段我使用了其它的工具(之后说明),在这个例子中不需要出现。 创建一个分析类图表
在你开始做任何类模型之前,你需要一个Visual Studio 项目包含至少一个类图表。你能够添加一个类图表到任何类型的项目,但我选择一个类库项目,因为我打算建立一个可再利用的类库-或API-来支持流通转换功能。
因此,我使用File | New | New Project 菜单选项来建立一个新的项目,并且我选择C#项目类型的类库模板。我命名这个项目为CurrencyClassLibrary。
注意:尽管我选择了演示类设计使用C#语言,但这之后我所描述的程序设计类也会使用Visual Basic 和其它.NET 语言。一旦项目倍建立,使用Project | Add New Item菜单选项就能将一个类的图表添加到项目中。选择类图表模板并给它一个适当的名字,我的例子中命名为AnalysisClasses.cd。
一旦你显示了一个类图表,即使是空的,我也能够访问如图3显示的工具箱。
![vstsclassdesigner-fig3](https://i-blog.csdnimg.cn/blog_migrate/47b8d2f2e6dba9d27bb4669f77454cc7.png)
图 3. 类设计器工具箱
这个工具箱提供了所有的类型-包括枚举,结构,类等等-你能够使用它移到类图表中。回忆在开始阶段,我说了通常类型和指定类的细微差别。让我们更详细地看看这些差别。
画出分析类图表
我将提供如何使用Visual Studio 2005类设计器画出最初类图表的说明。做完之后,我将建立一个如图2所显示的图表,你能够看到它的必要性。
添加ExchangeTransaction类
首先,我从工具箱中拖动一个类类型到类图表中,并且命名它为ExchangeTransaction。我右键点击图表上的类并从context菜单中选择Add | Property。我命名属性为fromAmount,并且为toAmount属性重复这个操作。
注意一个新的资源文件名为ExchangeTransaction.cs出现在解决方案浏览器中,并且包含了以下代码:
public class ExchangeTransaction
{
public int fromAmount
{
get { throw new System.NotImplementedException(); }
set {}
}
public int toAmount
{
get { throw new System.NotImplementedException(); }
set {}
}
}
你既可以通过在解决方案浏览器中打开文件查看代码,也可以通过右键点击图表上的类并从context中选择View Code来查看。
添加CurrencyCode枚举
我从工具箱中拖动一个枚举类型到类图表,并命名它为CurrencyCode。我右键点击枚举并从context菜单中选择Add | Member。我命名为成员USD,并为EUR成员重复这个操作。为每个成员,我在Properties窗口中设置了相同的值USD=1 and EUR=2。
注意一个新的资源文件名为CurrencyCode.cs出现在解决方案浏览器中,并且包含如下这些代码:
public enum CurrencyCode { USD = 1, EUR = 2, }
添加ExchangeRate类
我从工具箱拖动一个类类型到类图表中,并命名它为ExchangeRate。我右键点击图表上的类并从context菜单中选择Add | Field。我命名它为dateTime,并且为速率区域重复这个操作。为每个区域我使用Class Details窗口(图4)来设置他们的类型。
![vstsclassdesigner-fig4](https://i-blog.csdnimg.cn/blog_migrate/81545df3d1d78b703ac4ba8090e7734f.png)
图 4. Class Details 窗口
在这方面,非常值得说一些关于Class Details窗口。尽管你能在图表上直接编辑一些类的细节,包括类的名字和成员的名字,也能够编辑成员类型和可见性,但你必须使用Class Details 窗口。
接下来,我添加两个属性,就像我之前对ExchangeTransaction类做的,我命名这些属性为fromCurrency和toCurrency。我设置它们的类型为CurrencyCode。
注意一个新的资源文件名为ExchangeRate.cs出现在解决方案浏览器中,并且包含一下代码:
public class ExchangeRate
{
private double rate;
private DateTime dateTime;
public CurrencyCode fromCurrency
{
get { throw new System.NotImplementedException(); }
set {}
}
public CurrencyCode toCurrency
{
get { throw new System.NotImplementedException(); }
set {}
}
}
现在所有活动的结果最终是首先去掉的分析模型来支持流通转换;我将精炼一个模型到设计模型中。如果你决定跟着我的领导,但你的图表不能显示这些区域的类型和每个类的属性,你可以通过选择Class Diagram | Display Member Types菜单选项来简单地修复一下。
使用其它模型工具进行类分析
Visual Studio 2005不能够(至今)提供一个完全范围分析水平的图表符号,并且通常偏向与设计,执行和展开符号。
非常有可能你可以继续使用你最喜爱的UML模型工具来捕捉需求并勾画出最初的分析(或域)类。为了这个目的,我最喜爱的工具是Visio for Enterprise Architects,你将发现我合著了一本关于它的书。
注意:你能够在此找到这本书http://www.amazon.com/exec/obidos/tg/detail/-/0764543768
更客观地,一些使用Visio 或其它UML工具甚至免费的好处,是在Visual Studio 2005组件中对于商业和系统分析投资被大大简化了。
为了从类分析(在其它工具中)到类设计(在Visual Studio 2005中)的转换,对其它工具仅有的一个需求是它能够生成一种.NET语言的代码。一旦在你选择的语言中有了一些类,在Visual Studio 2005的代码中建立类图表将非常简单。
添加资源文件添加到你的项目中,并且拖动它们从解决方案浏览器直接到类图表中。你能够通过选择Project | Add New Item并选择类图表模板首先建立一个空的类图表,或你能够在解决方案浏览器的代码文件并且选择View Class Diagram 来建立一个类图表通过选择条目移植。
类图表做为代码查看
非常值得指出类图表不仅仅是代码之上的查看。这意味着你能够建立你喜欢的任何类图表,并且你能够拖动一个类从解决方案浏览器中到其它你希望的很多图表中,不必担心你在任何时间重复这个类。
做为代码上的查看,图表,以及代码本身总是保持同步。这就意味着你能够使用类设计器或代码编辑器根据你的参数做出相应的改变,这些改变能够自动反映到其它查看中。
类设计
假想我没有自己建立初始分析类,而是做为从商业或系统分析的输入,既像一个Visual Studio类也像一个Visio图表,在Visual Studio中生成代码并建立类图表。
这是一个很好的开始,不用怀疑,根据解释给我们-设计人员/开发人员-目的是需要支持流通转换。但分析人员有一些问题并且类模型不是很适合做为一个执行的基础。特别地,我发现了以下这些问题:
• | ExchangeRate类的区域不能使用属性完全地压缩。 |
• | ExchangeTransaction的属性不是一个适当的类型,通常是一个int 而不是double。 |
• | ExchangeTransaction的属性在它们得到的值没有潜在的区域。 |
• | 在ExchangeRate 类和CurrencyEnum 类之间的链接在fromCurrency和toCurrency成员中是固有的,但在图表中没有做直接的联合。 |
• | 在ExchangeTransaction 和 ExchangeRates中没有连接(联合),因此通常没有办法去记录ExchangeRate 在特殊的基于处理时间的ExchangeTransaction。 |
开始
如 果你按照我如何建立初始类图表的说明,你将有一个Visual Studio项目包含一个类图表以及三个C#源文件。如果你不按照我的说明,你将有一个空的项目,为了方便,我提供可以添加的四个文件: AnalysisClasses.cd,CurrencyCode.cs,ExchangeRate.cs,和 ExchangeTransaction.cs。
现在,我将通过右键点击解决方案浏览器中的项目,选择Add | New Item,并选择类图表模板来建立一个新的类图表名为DesignClasses.cd。我拖动三个类-实际是他们的源文件-从解决方案浏览器到新的图表中。
从分析类到设计类
我将通过定位之前列出的问题,设置关于展开的分析类图表到一个设计类图表中。在每一步骤保存重新建立的几乎相同的图表,我将通过显示图5中的最终结果开始。在我提示你做的时候,你可以使用这张图表,看到这些改变的效果。
![vstsclassdesigner-fig5](https://i-blog.csdnimg.cn/blog_migrate/135696f9d263d48e274de971ba69b620.png)
图 5. 流通交换设计类
改变区域或属性的类型
我需要找到的第一个问题是fromAmount的类型以及toAmount 在ExchangeTransaction上的属性,做为doubles这将比ints更好。如图6所示,我能够使用Class Details 窗口来改变任何成员属性或区域的类型。
![vstsclassdesigner-fig6](https://i-blog.csdnimg.cn/blog_migrate/6b304f12a95bc754b3ed15bd0cb319eb.png)
图 6. 在Class Details 窗口中改变一个成员类型
在你点击一个类的时候,如果你不能看见Class Details 窗口,你能够选择菜单选项View | Other Windows | Class Details,或通过右键点击类并使用内容菜单选项。
执行属性
ExchangeTransaction 类的fromAmount 和 toAmount 属性迄今没有被执行。这就是说,没有后面的区域或其它返回值机制会返回这些属性。不得不提及无论何处都存储这些属性的值。
为了执行这些属性,我打开代码查看(右键点击ExchangeTransaction 类并且选择View Code)并且写了以下C#源代码:
public class ExchangeTransaction
{
private double frmAmt;
private double toAmt;
public double fromAmount
{
get { return fromAmt; }
set { frmAmt = value; }
}
public double toAmount
{
get { return toAmt; }
set { toAmt = value; }
}
}
我制定了改变完全在代码中来强调改变能够被平等地放在代码或图表中。这两个查看是可以完全互换的。因此,在图表不能显示获得执行和设置方法时,将自动显示ExchangeTransaction 类的两个区域,不仅仅在当前的设计类图表中,也会反映到原始分析类图表上。
通过属性压缩区域
在ExchangeRate 类上,我有一些问题,两个区域没有压缩属性。这个问题能够在代码中解决,但我想告诉你一个更有意义的方法。
我能右键点击在类图表上的任何区域并从context菜单中选择Refactor | Encapsulate Field来产生如图7所示会话。
![vstsclassdesigner-fig7](https://i-blog.csdnimg.cn/blog_migrate/6c0a15b12da5eb0aa4653a45792d3913.png)
图 7. Encapsulate Field会话
这个会话引导我建立一个新的属性命名为DataTime 来压缩名为dateTime的区域;因此我接受了并采用了相同方法压缩了速率区域。
通过反映到突,你能够看到图表中的结果,结果的代码就是:
public class ExchangeRate
{
private double rate;
public double Rate
{ get { return rate; } set { rate = value; } }
private DateTime dateTime;
public DateTime DateTime
{ get { return dateTime; } set { dateTime = value; } }
}
观察联合
如果你回看原始分析类图表(图2),你将看到ExchangeRate 类有两个属性, fromCurrency 和 toCurrency,都是CurrencyCode类型。相同的图表显示了CurrencyCode做为一个枚举,因此你能够看到这些属性允许的值。
在设计类图表(图5)中,你能看到属性不再是可见的,但两条适当的连接线画在 ExchangeRate类CurrencyCode枚举中。这是更直观地方法来显示交换速率和流通代码之间的关系,并且如果你使用过UML,这些你将会非常熟悉。
在“属性”表示和“关联”表示之间切换是很简单的,右键点击每个属性并从内容菜单中选择Show As Association 即可;并且可以右键点击关联线并从内容菜单中选择Show As Property 即可切换回来。这两种查看是个人喜好的问题,在代码中是分辨不出来的。
注意: 一些UML工具通过不同方法提供了这些特性。它们允许成员类型根据预先确定的规则既被表示为属性也被表示为关联基本类型。例如,一个字符串对象能够被指定为一个基本类型,以至于所有的字符串在UML中总被显示属性而不是关联一个String类。
这有一个我添加的额外的关联,是在ExchangeTransaction类和ExchangeRate类中的一个关联。这是为了任何交换处理的,我不仅能侦测到from—and to- amounts ,还能够侦测到在强制时间转换-加上两个有关的流通的交换速率。
因为这个关联当前不存在,我必须通过工具箱中的关联条目添加它,点击ExchangeTransaction 类,并且拖动到ExchangeRate 类,我能够重命名这个关联,但默认的名字ExchangeRate 已经很好了。
所有工作的结果是我在图5展示的开端。
执行属性(再次访问)
当类是机器对你来说是新的时,做为软件专家有一些很好的机会你将设置合理化优先级,现在最终的关联被成形了。
确实不需要在ExchangeTransaction类上保持toAmt 区域很多,因为toAmount 能够从fromAmt 中计算出来,以及ExchangeRate 关联/属性的好处。因此,toAmt 区域能够被删除并且toAmount 属性能够被如下所示执行:
public double toAmount
{
get
{
// return toAmt;
return fromAmt * ExchangeRate.Rate;
}
}
注意因为我计算了toAmount,属性现在应该是只读的。这就是说,没有“设置”阻碍。我将这些更正给你自己的决定。
流通转换API
在这篇文章中我曾暗示要设计一个API,你或许有些带来一些一个或多个目标的想法,在所给内容中提供了有用的功能。迄今为止我设计了一个对象模型来支持一个API而不是API自己。
这个API包含两个类:
1. | BureauDeChange类,将使用getExchangeRate方法,在任何两个流通之间提供转换速率信息。 |
2. | CurrencyConverter类,将提供许多方法来转换一个流通到其它流通中的数量。 |
为了BureauDeChange最小,我允许为多种执行使用扩展的API。这种方法,一些卖主将能够完成提供转换速率信息,并且我能够选择最好价值服务的一个。
我将定义BureauDeChange 为一个简单执行的接口。不仅我能在类图表(我真实的动机)上演示接口,而且因为接口模型-类模型相反的-是很好的技术。
我不能预见多种CurrencyConverter执行,因此我将模型它为一个类
再一次,我首先向你演示结果图表,你就知道什么是你预期的,并且我能提及回到我的需求。图8显示了类图表APIClasses.cd.
![vstsclassdesigner-fig8](https://i-blog.csdnimg.cn/blog_migrate/edff0901e945c5216aa420f718235ac9.png)
图 8. API类
第一步是建立一个新的类图表名为APIClasses.cd,如图8所示。
BureauDeChange 接口和执行类
首先,我托拽一个接口类型从一个工具箱到图表上,并命名它为IBureaDeChange。我使用Class Details 窗口来添加一个名为getExchangeRate 的方法并使得返回类型参数如图9所示。
![vstsclassdesigner-fig9](https://i-blog.csdnimg.cn/blog_migrate/22c4b4dc51e99c50363dc22800dd4fe6.png)
图 9. IBureauDeChange的类细节
注意参数类型和返回类型符合(域)我之前定义的设计类,因而联系对象模型和API,基于这些对象周边的提供服务。
现在我需要建立一个那些接口的具体的执行。我拖动类从工具箱到图表中,并且命名它为BureauDeChange。我点击工具箱上的继承条目,点击BureauDeChange类,点击IBureauDeChange接口;指出类执行这些接口。像你在图9中看到的一样,最终结果是一个IBureauDeChange接“lollipop”出现在BureauDeChange类上。类设计器将自动为接口上的方法定义在类上提供方法存根。
CurrencyConverter类
完成API类图表I:
• | 从工具箱拖动一个类到图表中并命名它为CurrencyConverter。 |
• | 添加三个方法到图10中显示的使用Class Details 窗口的类中。 |
• | 从工具箱中使用关联条目画出CurrencyConverter类和IBureaDeChange接口的关联。 |
![vstsclassdesigner-fig10](https://i-blog.csdnimg.cn/blog_migrate/a5c090d5377bf1f4477cf34806e1a063.png)
图 10. CurrencyConverter的类细节
关联线显示了CurrencyConverter类依靠通过执行IBureaDeChange接口的类所提供的服务,事实上不需要默认的BureauDeChange执行类,我已经提供了。
也要注意,API类使用对象设计模型中的类做为它的参数和返回类型。
流通转换Web服务
在这方面,我分析并设计一个域对象模型来提供流通转换实体,加上API类,就提供了基于这些域类的流通转换功能。
API被设计成为一套标准的.NET类,并且接口从相同程序示实例中被直接调用。这是一个很好的方法来在行动中证明类设计,但不是我喜欢的API最终提供它们服务的方法。
如果你连续读过我之前的文章,这些API类似乎很熟悉。让我们看看图11,是我在那些文章中的一幅图,你将明白我的意思。
![vstsclassdesigner-fig11](https://i-blog.csdnimg.cn/blog_migrate/06cd845584fbd5145b85e8a1c2803c42.png)
图 11. 流通转换Web服务
我 的意思是设计一个BureauDeChange Web程序,包含一个提供交换速率信息的ExchangeRateService Web服务,并且一个CurrencyConversion Web程序包含提供流通转换功能的USDollarService和EuroService Web服务。在所有情况中,应该提供能够被远程调用的功能,而不是在相同程序实例中调用。
在我设计这些Web服务程序时,我指定了参数和返回类型如简单的ints, doubles等等。这就是通过这些Web服务被增强,因此从我的类设计工作获得好处,通过使用域对象-ExchangeTransaction,ExchangeRate,和CurrencyCode -做为返回和参数类型的完全过程。此外,保持执行相似的功能做为Web服务和标准类,这些服务的执行能够承担简单的我设计的API类。
结论
在本文中,我有一个逻辑过程,从类分析(能够使用Visual Studio 2005类设计器被执行) 到类设计 (做为重要连接到执行,Visual Studio类设计器是强制的)。
但不要认为类设计器被限制到初始类设计情况。类设计器版本一能够对一些额外用途,包括显示已有代码,分解(这篇文章提及过)和为文件目的画出图表进行优化。
初始分析和设计是对一个基于API形式的域对象而言的,但仅在我设计基于对象模型提供服务的附加类时才变为一个API。
这些服务能够做为正规类的方法提供,或做为真实的服务,如Web服务提供。在本文和我之前的文章中指出了如何将它们结合在一起。
Tony Loton是一位MCP他很多头衔,例如 Principal Consultant / Director of LOTONtech Limited (www.lotontech.com), Principal Consultant / Head of Microsoft Practice at Cogenture (www.cogenture.com),以及Associate Lecturer with the UK's Open University。他与Wiley / Wrox合著了Professional Visual Studio 2005 Team System (ISBN 0764584367)这本2005夏季出版的书。