 | Level: Intermediate Rajeshwari Rajendra (rajeshwari.r@in.ibm.com), Software Engineer, IBM India
13 Nov 2007 Learn how to model Microsoft® .NET C# applications by using IBM® Rational® Modeling Extension for .NET, which is available in IBM® Rational® Software Modeler, Rational Systems Developer, and Rational Software Architect. This article describes how to model various C# constructs, and the author assumes that you are familiar with basic UML modeling concepts and using Rational modeling tools.
IBM® Rational® Modeling Extension for Microsoft® .NET enables .NET application developers to use Rational modeling tools in designing applications. This extension is available in IBM® Rational® Software Modeler, IBM® Rational® Systems Developer, and IBM® Rational Software Architect, and it includes support for modeling C# applications.
Part 1 introduced modeling simple C# applications by using the C# profile and type library provided by Rational Modeling Extension for Microsoft® .NET. Therefore, you should now be familiar with modeling C# classes, structures, interfaces, delegates, enumerations, fields, and methods. This article continues to use the same example of the graphics library project used in Part 1 to help you understand how to model other C# concepts, such as indexers, properties, operators, and others.
Part 2 builds on the previous article by describing how to use this extension to model these constructs:
- Constructors and destructors
- Operators
- Properties
- Indexers
- Events
- Attributes
- Namespace
This article also explains how to validate your model for C# applications.
Modeling constructors and destructors
Like C# methods, a constructor or destructor is also modeled as a UML operation with optional an <<CSharp Method>> stereotype for specific modifiers (for example, extern). A UML operation representing a constructor is given the same name as its parent class or structure name. A destructor is named in a similar manner, except that it has a ~ (tilde) followed by the parent's name.
A return type should not be set for a UML operation representing either a constructor or a destructor. Parameters are added to the constructor similarly to how you add parameters to method. A static constructor is modeled by setting the static property of the corresponding UML operation.
Figure 1 shows a constructor with two arguments of type Point and a destructor modeled for the DrawingSurface class of the sample application used here for illustration purposes.
Figure 1. C# constructor DrawingSurface(Point start,Point end) and destructor ~DrawingSurface()
Modeling operators
C# operators are modeled as UML operation with optional <<CSharp Method>>
stereotype for specific modifiers, such as extern. A unary operator
is named by using the key word operator followed by the unary operator symbol. For example, the unary increment operator is named as operator ++. A return type and a single parameter are set for UML operation that represents a unary operator.
A UML operation representing a binary operator is named similarly to unary operator, but the symbol is one of the binary operators. Also, two parameters are set, and the return type is specified for a UML operation corresponding to a C#
binary operator. For example, a C# operator of == (two equal signs) is named operator == in the UML model. The conversion operators in C# are represented by UML operations named as either implicit operator or explicit operator. Such a UML operation should specify the target type of the conversion as the return type and the source or input type of the conversion as a parameter type.
Figure 2 shows an examples for modeling C# unary, binary, and conversion operators. The unary operator ++ takes a parameter of type Point and returns a Point. The binary operator !=
takes two parameters each of type Point and returns a bool type. The implicit conversion operator is defined, which converts a Point type to int.
Figure 2. C# unary, binary, and conversion operators
Modeling properties
A C# property is modeled as a UML property (either a UML attribute or an association end) along with a <<CSharp Property>> stereotype. The UML property should have the same name and type as its
corresponding C# property. Modifiers for a C# property are available as Boolean stereotype properties. For example,
abstract, virtual, extern, and override are available in the
<<CSharp Property>> stereotype properties.
In addition to the modifiers, the stereotype has a property called accessors that which can be set to one of the following values: read-only, write-only or read & write. The read-only value should be used whenever the corresponding C# property has only the get accessor method. Similarly, write-only should be used whenever the
corresponding C# property has only set accessor. When the C# property has both get and set accessors, the read & write value should be used.
An abstract property is modeled as a UML property with <<CSharp Property>> stereotype with its abstract stereotype property set to true. For this example, you will model a C# property called distance for the Point structure. This property represents the distance of the point from its origin. Because the distance is calculated from the X and Y coordinates, you will model it as a read-only property. To do this, follow these steps (also see Figure 3):
- Add a public field named distance to Point, and set its type to int.
- Apply the
<<CSharp Property>> stereotype to the distance field.
- Set the accessors property of the stereotype to read-only
Figure 3. C# distance property
Modeling indexers
A C# indexer is modeled as a UML operation with <<CSharp Indexer>> stereotype. A UML operation representing an indexer should always be named as
this
. The formal parameters of the C# indexer become the parameters of the corresponding UML operation and the type of the indexer becomes the return type of the UML operation. Indexer modifiers like new, virtual, extern etc. are available as stereotype properties. A sealed indexer is represented by
selecting the Leaf property of the corresponding UML operation.<<CSharp Indexer>> has a property
named accessors which can take values : read-only, write-only and read & write depending on whether the C# indexer has only get accessor or only set accessor or both get and set accessors respectively. This is very much similar to accessors property of <<CSharp Property>>.
For this example (Figure 4), you will model a read-only indexer (thus it has only a get accessor) in
the DrawingSurface class. This indexer will have two parameters of type int, and it will return a Point type. Basically, the purpose of this indexer is to return a point corresponding to a given row and column on the
drawing surface. Follow these steps:
- Add a UML operation named
this to the UML DrawingSurface class.
- Apply the
<<CSharp Indexer>> stereotype to the operation that you added in previous step.
- Add two parameters of type int to the operation, and name them
row and column.
- Set the return type of the operation as Point structure.
- Set the property accessors in the stereotype to read-only (see Figure 4).
Figure 4. C# indexer Point this[int row, int column]
Modeling events
A C# event is modeled as a UML property (either a UML attribute or an association end), along with a <<CSharp Event>> stereotype. The UML property should have the same name as its corresponding C#
event. The type of the UML property should be a UML class with a <<CSharp Delegate>> stereotype. Modifiers for a C# event are available as Boolean stereotype properties. For example, abstract,
virtual, extern, override, and other modifiers are available in the <<CSharp Event>> stereotype properties. The accessors stereotype property is set to true if the event has its accessors (add or remove); otherwise, it is set to false.
This example (Figure 5) uses the handleResize() delegate for an event named
mouseDrag in the class DrawingSurface class. To do this:
- Add a public UML attribute to the
DrawingSurface class, and apply the
<<CSharp Event>> stereotype.
- Set the attribute's type to a UML class that represents the
handleResize delegate.
- Set the accessors stereotype property to true, thereby indicating that
add and remove accessors will be specified.
Figure 5. C# public event for handleResize mouseDrag
Modeling attributes
The C# language allows programmers to provide certain kinds of declarative
information through attributes attached to program entities. These
attributes are defined as attribute classes. Attribute classes can be modeled in a
manner similar to any other class, and they have a generalization relationship with
a System.Attribute. The attribute use with a specific entity is depicted
as a stereotype property named attributes in the corresponding stereotype
for the entity. For example, an attribute declared for a C# class can be set as a
string in the attributes stereotype property in the <<CSharp
Class >> stereotype.
For this example, you will model an attribute class called
TestAttribute and its use (also see Figure 6 and Figure
7):
- Create a UML class named
TestAttribute.
- From the Project Explorer, look for the
System.Attribute class in the
References section of an imported C# project, and drag it onto a
diagram. (Importing a C# project is described in a a separate
article about using this Rational extension to visualize .NET applications.)
- Drag the
TestAttribute class onto the diagram also, and show a
generalization relationship from TestAttribute to
System.Attribute.
- Apply the
<<CSharp Class >> stereotype to TestAttribute.
- Set the attributes stereotype property in the
<<CSharp
Class >> to [AttributeUsage(AttributeTargets.Class,
AllowMultiple = true)].
- Now, to use this attribute on any of your classes, such as
GraphicObject,
apply the <<CSharp Class>> stereotype and
set its attributes stereotype property to [TestAttribute].
Figure 6. C# TestAttribute attribute class representation
Figure 7. C# Attribute use for TestAttribute
The attributes property in various stereotypes is are used in a similar
manner, including the properties for these stereotypes:
-
<<CSharp Delegate >>
-
<<CSharp Interface >>
-
<<CSharp Method >>
Modeling namespace
A C# namespace is modeled as a UML package. All types in a namespace are modeled
as UML types in the corresponding package. The package should be named without any
special characters. As an example, a class called MyClass in a namespace
called com.ibm should be modeled as a class in a package called
ibm, which is nested in another UML package called com, rather than
creating a class for
MyClass in a UML package named com.ibm.
Validating your model
After a C# application has been modeled in Rational Modeling Extension for .NET,
you can verify the
correctness of the model by using the Model Validation feature available in
version 7.0.0.1 and later of this extension. To validate a model:
- Select the model
in the Project Explorer.
- Right-click and choose
Validate from the pop-up menu (see Figure 8).
The model is then validated and any errors or
warnings are shown in the error log. For example, model validation will catch errors such as incorrect modeling
of C# delegates.
Figure 8. Model validation
Resources Learn
- Read
Modeling C# applications using Rational Modeling Extension for .NET,
Part 1.
- Find out more about
IBM Rational Modeling Extension for Microsoft .NET
on developerWorks..
- To learn how to import a C# project, read
IBM Rational Modeling
Extension for Microsoft .NET: Visualizing .NET applications, an IBM®
developerWorks® article by Lalitha Kishore and Darpan Saini (March
2007).
- Visit the
IBM Rational Modeling Extension for Microsoft .NET
area on developerWorks for technical documentation, how-to articles, education,
downloads, and product information.
- Visit the
Rational Software Architect
area on developerWorks for technical documentation, how-to articles, education,
downloads, and product information.
- Subscribe to the
developerWorks Rational zone newsletter.
Keep up with developerWorks Rational content. Every other week, you'll
receive updates on the latest technical resources and best practices for the
Rational Software Delivery Platform.
- Browse the
technology bookstore
for books on these and other technical topics.
Get products and technologies
Discuss
About the author  | 
|  | Rajeshwari Rajendra is a software engineer in the IBM India Software Lab, working on the Rational Systems Developer team. Her expertise includes XML query technologies, such as XPath and XQuery, and UML modeling and transformations (specifically, C# and C++). She has a Master's degree (MCA) from Bangalore University, India. |
Rate this page
|  |