Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Modeling C# applications using Rational Modeling Extension for Microsoft .NET

Modeling C# arrays, pointers, partial and generic types

Rajeshwari Rajendra (rajeshwari.r@in.ibm.com), Software Engineer, IBM India
Rajeshwari Rajendra
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.

Summary:  This article is intended for Microsoft® .NET application developers. It explains how to model .NET C# applications using the modeling capabilities available in Rational Modeling tools as extended by IBM® Rational® Modeling Extension for Microsoft .NET. This extension can be used with IBM® Rational® Software Modeler, IBM® Rational® Systems Developer, and IBM® Rational® Software Architect. The article assumes that you are familiar with basic UML modeling concepts using Rational modeling tools.

Date:  20 May 2008
Level:  Intermediate PDF:  A4 and Letter (873KB | 26 pages)Get Adobe® Reader®
Also available in:   Chinese

Activity:  4246 views
Comments:  

IBM® Rational® Modeling Extension for Microsoft® .NET is an extension into Rational Modeling tools to aid .NET application developers design their applications. At the time of writing this article, Rational Modeling Extension for Microsoft .NET supports modeling of C# applications. The previous two parts of this article series explained basic modeling concepts for C# application. This article, the third in the series, will describe the steps to model the following C# concepts using Rational Modeling Extension for Microsoft .NET

  • Arrays
  • Pointers
  • Partial types
  • Generics

This article will discuss the usage of a mapping model to direct code generation into files other than default ones.

Introduction

This article covers advanced modeling concepts for C# application developers. The article presumes that you are already familiar with basic C# modeling concepts covered in the other articles in this series -- Modeling C# applications using Rational Modeling Extension for Microsoft .NET: Part 1 and Modeling C# applications using Rational Modeling Extension for Microsoft .NET: Part 2-- see Resources. All of the following sections will require you to have created a model and imported a C# profile, as explained in Part 1.


Modeling C# Arrays

C# arrays can be single dimensional, multi-dimensional, or jagged arrays. When you declare an array type, the size of the array is not specified. To model an array, use the <<CSharp Array>> stereotype on the UML property (attributes) or UML method parameters. Once the stereotype is applied, you can specify the value for the rank_specification stereotype property, which denotes whether an array is 1-dimensional, multi-dimensional or jagged array.

To better understand, model a UML class named ArraysExample having three attributes that represent single-dimensional, multi-dimensional, and jagged (array of arrays) arrays. To do this, follow these steps.

  1. Create a UML class and name it ArrayExample. Make sure that the C# profile is applied on the UML model.
  2. Create a UML attribute in the class and name it singleDimArray. Set its Type to C# <Primitive Type> int and its Default Value to new int[5].
  3. Apply the <<CSharp Array>> stereotype and set the stereotype property rank_specification to [ ].
  4. Similarly, create a UML attribute named multiDimArray with Default Value as new int [ 6, 4] and set the rank_specifications stereotype property to [ , ].
  5. In the same manner create a UML attribute named jaggedArray with Default Value as new int[3][ ] and set the rank_specifications stereotype property to [ ] [ ], as shown in Figure 1.

Figure 1. Modeling C# arrays using the <<CSharp Array>> stereotype
Properties view with General and Stereotypes tab

Modeling C# pointers

In C#, pointers can be used in an unsafe context. An unsafe context is enabled by using the unsafe modifier in the declaration of a type or member. In order to model an unsafe context in UML, set the unsafe stereotype property to true. The unsafe stereotype property is available in stereotypes that can be applied on UML Class, Interface, attribute, or operation. For example, in order to use pointers in an unsafe context, you can set the unsafe modifier in any of <<CSharp Class>>, <<CSharp Interface>>, <<CSharp Method>>, <<CSharp Field>>, <<CSharp Indexer>>, and so on to true.

As an example, you will model a class Node for a binary tree, with 2 pointers to the left and right child nodes. To do this, follow these steps.

  1. Create a UML class and name it Node. Since you need to use the unsafe modifier, apply the <<CSharp Class>> stereotype and set the unsafe stereotype property to true.
  2. Now add an attribute to the class and name it left. Set its Type to Node. Apply the stereotype <<CSharp Pointer>> and set its indirection_specification property to *.
  3. In a similar manner, add another attribute (pointer) with the name right. You have created two pointers of type Node * in the Node class, as shown in Figure 2.

Figure 2. Modeling C# Pointers using <<CSharp Pointer>> stereotype
Properties view, Stereotypes tab

Modeling C# Partial types

In C#, it is possible to give partial definitions of classes, interfaces, and structures spread across multiple files. Basically the concept of partial types allows you (as the application developer) to define parts of a type across multiple files by using the keyword partial with each definition. By using the concept of partial types, the developer can encapsulate different perspectives (data or behavior) of an object in different files. Finally, the actual type is the union of all of the different definitions. For more information on partial types, please refer to the C# language specification.

This article will now show you how to define partial types in Rational Modeling Extension for Microsoft .NET. To start defining a partial type, create the corresponding UML type (class or interface) in the required package. You may use the <<CSharp Struct>> stereotype on the UML class if you are defining a partial struct. This UML type will have the same name as its equivalent C# construct, but will not have any attributes or operations.

Basically, this type will have empty definition. In order to define individual definitions of this partial type, you create as many UML types as the number of definitions, and give some arbitrary but meaningful names to them. The names do not matter for these individual UML types, which represent partial definitions. Each of these types will contain the attributes, operations, and so on corresponding to the partial definition being represented by them. At the end, you need to create a UML dependency relationship stereotyped as <<CSharp Partial>>, starting from each individual definition to the UML type with an empty definition (the type whose name is the same as the C# partial type, but with an empty definition).

To better understand the concept, model an ATM Machine with two perspectives -- one from the user perspective and the other from the bank perspective -- and model these perspectives as two partial definitions.

If you were to define the ATM machine from the user perspective, you would think of operations such as the following:

  • Insert ATM card
  • Receive PIN
  • Disburse money

When you look at ATM machine from bank perspective, on the other hand, you would think of operations such as:

  • Validate the card
  • Validate the PIN
  • Reduce the balance in the user account

Both of these perspectives are defining the ATM machine, but from different angles. Therefore, the ATM machine on the whole has all of the operations from both perspectives. You will now take a look at the steps required to model the partial definitions of the ATM machine.

  1. Create a UML class and name it ATM_Machine.
  2. Create another UML class and name it ATM_UserPerspective. Next, create a UML dependency relationship from this class to ATM_Machine. Also, apply the stereotype <<CSharp Partial>> on the dependency relationship. This indicates that ATM_UserPerspective is one of the partial definitions of the class ATM_Machine.
  3. Add UML operations such as insertCard(String cardNumber), enterPIN(int PIN), enterAmount(long amount), and disburseCash( ), and so on to ATM_UserPerspective.
  4. Now create another UML class named ATM_BankPerspective, and create a UML dependency relationship from this class again to ATM_Machine. Apply the stereotype <<CSharp Partial>> on the dependency relationship to indicate that ATM_BankPerspective is another partial definition of the class ATM_Machine, as shown in Figure 3.
  5. Now add UML operations such as validateCard( ), checkAccountBalance( ), reduceBalance(String accountNumber, long amount). and so on to ATM_BankPerspective.

    Note: When you run a UML-to-C# transform on a model containing partial types, each partial definition is generated in a file whose name is the same as the definition name, but the actual type in that file will have the name of the corresponding partial type (the name of the empty UML type where the UML dependency relationship ends) with the partial keyword. To re-direct the code generation of the individual definitions into a different file, use a mapping model (as described in a later section).

Figure 3. Modeling C# partial types using the <<CSharp Partial>> stereotype
table with Stereotype, Profile, and Required columns

Modeling C# Generics

In C#, you (as a developer) can define generics for classes, interfaces, structs, delegates, and methods. This article will discuss how to model each of these with examples. Before you proceed, though, you need to understand two aspects of C#: a generic declaration and a generic instantiation.

A generic declaration only defines the template of a type, delegate, or a method. The usage of the generic requires instantiation of generic by providing values to the generic (or template) parameters.

To understand the concept, consider an example. Try to model a simple Library system that has a number of shelves, and each shelf has a number of books that are arranged in a sorted order based on their title. Since list and sorted lists can be used to store any object, you will model them as generics and instantiate them to store specific objects (books). To model this, you will define a generic list and use it to define a sorted list. The sorted list will be instantiated to store information on books.

The code being represented in the above example is shown in Listing 1.


Listing 1. Sample code for the library system modeled using generics
                
using System;

public class List<T>
{
    public bool isEmpty()
    {
        return true;
    }
    public int getSize()
    {
        return 0;
    }
    public T get(int index)
    {
        return null;
    }
}
public class SortedList<X> : List<X>
{
    public void sort(bool ascendingOrder)
    {
    }
}
public class Book
{
}
public class Shelf
{
    SortedList<Book> sortedBooks;
}

public class Library
{
    List<Shelf> shelves;
}

The steps that you need to perform to create the model (Listing 1) of a library system are as follows.

  1. Create a class named List. Right-click the class and add a template parameter with name T. Add operations such as isEmpty():bool ,getSize():int.
  2. You will also need to create a method that uses the template parameter. Add a method called get() with return type as the template parameter T from the method (as shown in Figure 4), and an input parameter named index whose type is int.

You can also use the template parameter T for an attribute’s type, in the same way as it was used for the method’s return type.


Figure 4. Selecting the template parameter as the return type of the method
Template parameter in tree view
  1. Similarly, create another class named SortedList and add a template parameter X. Because you want SortedList to extend List, and to use List you need to create an instantiation of the List class, create a placeholder class.

This placeholder class should represent the instantiation of List by binding the template parameter T to the template parameter of X. To accomplish this, create a class named ListBase and add a binding relationship from ListBase to List, and then bind the parameter T to X, as shown in Figure 5.


Figure 5. Binding template parameter
diagram and table
  1. Add a method like sort(ascendingOrder:bool) to SortedList and create a generalization from SortedList to ListBase, as shown in Figure 6.

Figure 6. Generic Class instantiation by using bind relationship
diagram with List, ListBase, and SortedList
  1. Create UML classes named Shelf and Book.
  2. Now, model a collection of sorted books in a shelf. For this, create a binding class SortedBooksList with a binding to SortedList by setting X to Book. Create a one-directional association from Shelf to SortedBooksList and name the association end sortedBooks. This represents the attribute declaration SortedList<Book> sortedBooks; shown in Listing 1.
  3. Create a template binding class named ShelvesList with a binding to the List class by setting the parameter T to Shelf. This represents List<Shelf>.
  4. Finally, create a Library class with an association to ShelvesList and name the association end as shelves. This represents the attribute declaration List<Shelf> shelves; in the Library class of Listing 1.

The previous example covered the concepts of generic declaration and instantiation. Generic methods are similarly modeled by adding template parameters on the UML operation.


Mapping Model

A mapping model is used while configuring C# transformations. It is useful when you want to control the physical organization of your source code, which may be different from the default. For example, by default the UML-to-C# transform generates a class in a file with the same name as the class. But if you want two or more classes to exist in the same file, then you could use a mapping model to specify the hierarchy and contents of the source files.

In addition, when you use partial classes, a mapping model is used to direct each definition of the partial class into a file based on your requirements. Basically, a mapping model is nothing but another UML model that captures information on the physical organization of the source code. It is a model usually consisting of packages and artifacts, with manifestations to UML types from the logical design model of the application.

The UML packages in a mapping model represent folders on a file system, and the UML artifacts within the UML packages represent source files in those folders. The artifact should be given the source file name ending with an extension of .cs Each artifact has one or more manifestations, depending on the number of the classes or types to be contained in that file.

For example, in the library system discussed in the previous section, suppose you want this configuration:

  • The classes Library, Shelf, and Book in a single file named LibrarySystem.cs
  • The LibrarySystem.cs file in a folder named library
  • All the generics (List, SortedList) to be generated in a file named LibraryGenerics.cs
  • This file under a folder hierarchy library/generics/collections

To do this, create a mapping model as follows:

  1. Create a UML package named library in the model. This represents the folder library under the C# project root.
  2. Create an artifact named LibrarySystem.cs under the package library. This represents the file LibrarySystem.cs under the folder library.
  3. Create three manifestation relationships from the artifact created above to the UML classes Library, Shelf ,and Book from the logical design model of the application.
  4. Create a UML package named generics under the library package. This represents the folder library/generics under the C# project.
  5. Create a UML package named collections under the generics package. This represents the folder library/generics/collections under the C# project.
  6. Create an artifact under the collections package and name it LibraryGenerics.cs
  7. Create two manifestation relationships from the above artifact to the List and SortedList classes from the logical design model.

You can specify this model as the mapping model in the transformation configuration editor. It will be used by the UML-to-C# transform to determine the directory structure of source code during code generation, and the model will also be updated when the C#-to-UML transform is run.


What you have learned

This article has discussed advanced C# modeling topics. It has outlined the concepts of modeling C# pointer and array types. Also, after reading this article, you should be able to model partial and generic types, and use a mapping model to design the file system view of the source code.


Resources

Learn

Get products and technologies

Discuss

About the author

Rajeshwari Rajendra

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.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=308025
ArticleTitle=Modeling C# applications using Rational Modeling Extension for Microsoft .NET
publish-date=05202008
author1-email=rajeshwari.r@in.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers