级别: 中级 Rajeshwari Rajendra (rajeshwari.r@in.ibm.com), 软件工程师, IBM 印度
2008 年 1 月 28 日
学习如何利用 IBM® Rational® Modeling Extension for .NET(该扩展也可以在 IBM® Rational® Software Modeler、Rational Systems Developer 和 Rational Software Architect 中使用)对 Microsoft® .NET C# 应用程序建模。本文介绍了如何对各种各样的 C# 结构建模,作者假设您熟悉基本的 UML 建模概念,以及 Rational 建模工具的使用。
IBM® Rational® Modeling Extension for Microsoft® .NET 允许 .NET 应用程序开发人员使用 Rational 建模工具设计应用程序。它是可用在 IBM® Rational® Software Modeler、IBM® Rational® Systems Developer 和 IBM® Rational Software Architect 中的扩展,并且包括对 C# 应用程序建模的支持。 第 1 部分介绍了利用 Rational Modeling Extension for Microsoft® .NET 提供的 C# 概要文件和类型库对简单的 C# 应用程序建模。因此,您现在应该熟悉了对 C# 类、结构(Structure)、接口(interface)、委托(delegate)、枚举(enumeration)、字段(field)和方法(method)的建模。本文继续使用与第 1 部分中使用的图形类库相同的实例来帮助您了解如何对其他的 C# 概念,例如索引器、属性、操作,及其它建模。 第 2 部分建立在前一篇文章的基础上,它介绍了如何使用该扩展对这些结构建模:
- 构造方法和析构方法
- 操作符
- 属性(property)
- 索引器
- 事
- 属性(attribute)
- 命名空间
本文还介绍了如何验证您的 C# 应用程序的模型。 对构造方法和析构方法建模 像 C# 方法一样,构造方法(constructor)和析构方法(destructor)也被建模为 UML 操作,并且带有针对专门的修饰符(举例来说,extern)的可选择的 <<CSharp Method>> 原型。表示构造方法的 UML 操作有和其母体类或结构名相同的名字。析构方法按类似的方式命名,除了它的母体名前有一个 ~(否定号)。 不应该为表示构造方法或析构方法的 UML 操作设置返回类型。向构造方法添加参数的方式类似于向方法添加参数的方式。通过给相应的 UML 操作设置 static 属性来对 static constructor 建模。 图 1 展示了为示例应用程序(在这里用于举例)的 DrawingSurface 类建模的带有两个 Point 类型参数的构造方法和一个析构方法。 图 1. C# 构造方法 DrawingSurface(Point start,Point end) 和析构方法 ~DrawingSurface()
对操作符建模 C# 操作符(operators)被建模为带有针对特定修饰符,例如 extern,的可选的 <<CSharp Method>> 原型的 UML 操作。单目操作符(unary operator) 是通过在关键字 operator 后跟单目运算符符号来命名的。举例来说,单目增量运算符命名为 operator ++。表示单目运算符的 UML 操作还设置有返回类型和一个参数。 表示 双目运算符(binary operator) 的 UML 操作的命名方式类似于单目运算符,但符号是双目运算符之一。同样,设置有两个参数,并且为 C# 双目运算符相对应的 UML 操作指定了返回类型。举例来说,C# 操作符 == (两个等号)在 UML 模型中为 operator == 。C# 中的转换操作符由名为 隐式操作符(implicit operator) 或 显式操作符(explicit operator) 的 UML 操作表示。这样的 UML 操作应该将转换的目标类型指定为返回类型,转换的源或输入类型指定为参数类型。 图 2 显示了为 C# 单目、双目,和转换操作符(conversion operator)建模的实例。单目运算符 ++ 的参数是类型 Point 的,并返回 Point。双目运算符 != 的两个参数是类型 Point 的,并且返回 bool 类型。隐式转换操作符将 Point 类型转换为 int 。 图 2. C# 单目、双目,和转换操作符
对属性(property)建模 C# 属性(propertie)被建模为带有 UML 属性 <<CSharp Property>> 原型的 UML 属性(UML attribute 或关联端)。UML 属性应该与其相应的 C# 属性具有相同的名称和类型。C# 属性的修饰符作为 Boolean 原型属性。举例来说,abstract、virtual、extern 和 override 在 <<CSharp Property>> 原型属性中都有。 除了修饰符,原型还拥有名为 accessors 的属性,可以将该属性设置为以下值之一:read-only、write-only 或 read & write。在相应的 C# 属性只有 get accessor 方法时应该使用 read-only 值。类似的,在相应的 C# 属性只有 set accessor 时,应该使用 write-only。当 C# 属性有 get 和 set 存取器时,应该使用 read & write 值。 抽象属性被建模为带有 <<CSharp Property>> 原型的 UML 属性,它的 abstract 原型属性被设置为 true。对于此实例,您将为 Point 结构对名为 distance 的 C# 属性建模。该属性表示从原点到该点之间的距离。因为距离是由 X 和 Y 坐标计算的,所以您将把它建模为只读属性。要做这些,依据以下步骤(也参见图 3):
- 向 Point 添加名为 distance 的 public 字段,并将其类型设置为 int。
- 向 distance 字段应用
<<CSharp Property>> 原型。 - 将原型的 accessors 属性设置为 read-only
图 3. C# distance 属性
对索引器建模 C# 索引器(indexer)被建模为带有 <<CSharp Indexer>> 原型的 UML 操作。表示索引器的 UML 操作应该总是被命名为 this 。C# 索引器的形式参数成为相应的 UML 操作的参数,而索引器的类型成为 UML 操作的返回类型。索引器修饰符,像 new、virtual、extern 等等用作原型属性。通过选择相应的 UML 操作的 Leaf 属性来表示 sealed 索引器。<<CSharp Indexer>> 拥有名为 accessors 的属性,其取值为:read-only 、write-only 和 read & write ,这依据 C# 索引器是否只有 get accessor 或 set accessor 或者分别拥有 get 和 set accessors 。这非常类似于 <<CSharp Property>> 的 accessors 属性。 对于本实例(图 4),您将对 DrawingSurface 类中的只读索引器建模(因而它只有 get 存取器)。该索引器将有两个 int 类型的参数,并且它将返回 Point 类型。本质上,该索引器的目的是返回一个与绘制面上已知的行和列相对应的点。依据以下步骤:
- 向 DrawingSurface 类添加名为
this 的 UML 操作。 - 向您在前面步骤中添加的操作应用
<<CSharp Indexer>> 原型。 - 向操作添加两个 int 类型的参数,并将其命名为
row 和 column 。 - 将操作的返回类型设置为 Point 结构。
- 将原型的 accessors 属性设置为 read-only(参见图 4)。
图 4. C# 索引器 Point this[int row, int column]
对事件建模 C# 事件(event)被建模为带有 <<CSharp Event>> 原型的 UML 属性(UML attribute 或关联端)。UML 属性应该和其相应的 C# 事件有相同的名称。UML 属性的类型应该是带有 <<CSharp Delegate>> 原型的 UML 类。C# 事件的修饰符作为 Boolean 原型属性。举例来说 example、abstract、virtual、extern、override ,和其它修饰符在 <<CSharp Event>> 原型属性中可用。如果事件有它的存取器(add 或 remove )的话,将 accessors 原型属性设置为 true,否则将其设置为 false。 该实例(图 5)将 handleResize() 委托用于 DrawingSurface 类中的名为 mouseDrag 的事件。要这样做:
- 向
DrawingSurface 类添加 public UML 属性,并应用 <<CSharp Event>> 原型。 - 将属性的 type 设置为表示
handleResize 委托的 UML 类。 - 将 accessors 原型属性设置为 true,从而说明将指定 add 和 remove accessors。
图 5. C# 对于 handleResize mouseDrag 的公共事件
对属性建模 C# 语言允许程序设计人员通过附加在程序实体上的 attributes 来提供某些类型的说明性的信息。这些属性(attribute)被定义为 属性类。属性类建模的方式类似于任何其他的类,并且它们和 System.Attribute 有泛化关系。与具体实体一起的属性被描述为相应的实体的原型中名为 attributes 的原型属性。举例来说,为 C# 类声明的属性可以设置为 <<CSharp Class >> 原型中的 attributes 原型属性中的字符串。 对于该实例,您将对名为 TestAttribute 的属性类及它的使用来建模(也参见图 6 和图 7):
- 创建名为
TestAttribute 的 UML 类。 - 在 Project Explorer 中,在所导入的 C# 项目的 References 部分中寻找
System.Attribute 类,并将其拖到图上。(导入 C# 项目的方法参见关于使用该 Rational 扩展来可视化 .NET 应用程序的另外一篇文章。) - 也将
TestAttribute 类拖到图上,并显示从 TestAttribute 到 System.Attribute 的泛化关系。 - 向 TestAttribute 应用
<<CSharp Class >> 原型。 - 向 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 设置
<<CSharp Class >> 中的 attributes 原型属性。 - 现在,对您任意的类应用该属性,例如
GraphicObject ,应用 <<CSharp Class>> 原型,并将其 attributes 原型属性设置为 [TestAttribute]。 图 6. C# TestAttribute 属性类的表示
图 7. 用于 TestAttribute 的 C# Attribute
在各种各样的原型中,attributes 属性的用法都类似,包括这些原型的属性:
<<CSharp Delegate >> <<CSharp Interface >> <<CSharp Method >>
对命名空间建模 C# 命名空间(namespace)建模为 UML 包。命名空间中的所有类型建模为相应的包中的 UML 类型。对包的命名不应该有任何特殊的字符。举例来说,名为 MyClass 类处于 com.ibm 的命名空间中,应该将它建模为 ibm 包中的类,该包处于另一个名为 com 的 UML 包中,而不是为 MyClass 在名为 com.ibm 的 UML 包中创建一个类。
验证您的模型 当在 Rational Modeling Extension for .NET 中对 C# 应用程序建模之后,您可以通过该扩展的版本 7.0.0.1 和之后的版本中可用的 Model Validation 特性来验证模型的正确性。要验证模型:
- 在 Project Explorer 中选择模型。
- 单击右键,并在弹出菜单中选择 Validate(参见图 8)。
然后验证模型,在错误日志中显示出任何的错误或警告。举例来说,模型验证会捕获例如对 C# 委托的不正确的建模的错误。 图 8. 模型验证
|