StarTeam SDK for .NET - Getting Started

The StarTeam SDK for .NET is a native .NET implementation of the StarTeam SDK.

This document provides basic information intended to help you get started using the StarTeam SDK for .NET. It assumes that you are already familiar with the StarTeam SDK for Java and COM, and focuses mainly on .NET-specific features.

For more detailed information on the StarTeam SDK programming interfaces, consult the StarTeam SDK for .NET help file.

Overview

The StarTeam SDK for .NET is designed to support the following:

To support these development scenarios, the StarTeam SDK for .NET actually provides two complete sets of APIs:

The C# APIs are actually implemented as thin wrapper classes, using the J# APIs in their underlying implementation. In fact, the two APIs are designed to work well together; that is, application code written to the C# APIs can interoperate with application code written to the J# APIs.

The following sections describe how each of the application types listed above would use the StarTeam SDK for .NET APIs.

Writing .NET Applications in J#

Core applications are written in Java and cross-compiled to the .NET platform using Microsoft Visual J#. Such applications use the J# flavor of the StarTeam.NET APIs, which are found in Borland.StarTeam.Core.dll.

This scenario is shown graphically in the figure below.

The J# APIs are virtually identical to the Java APIs.

Writing .NET Applications in C#

Native applications written from scratch for the .NET platform are usually written in C# or Visual Basic .NET. Such applications will use the C# flavor of the StarTeam.NET APIs, which are found in Borland.StarTeam.dll. 

This scenario is shown graphically in the figure below.

If you are already familiar with the StarTeam Java APIs (or the .NET APIs for J#), then the C# APIs should look familiar. The basic object model is the same. The differences are designed to make the C# APIs integrate better into the .NET environment.

The remainder of this section describes the most important differences between the C# and J# flavors of the StarTeam .NET APIs.

Namespace

The J# APIs use the com.starbase.starteam namespace; the C# APIs use the Borland.StarTeam namespace.

Naming Conventions

The J# APIs use method names that start with a lowercase letter; the C# APIs use method names that start with an uppercase letter.

Properties

The C# APIs use .NET properties where applicable; the J# APIs use get/set methods that serve as property accessors. For example, the following J# code that uses the J# APIs:

v = project.getDefaultView(); 

would become the following C# code using the C# APIs:

v = project.DefaultView;

Indexers

The C# APIs use indexers where applicable; the J# APIs use get/set methods. For example, the following J# code that uses the J# APIs:

s = cr.get("Synopsis"); 
cr.put("Synopsis", "Just testing..."); 


would become the following C# code using the C# APIs:

s = cr["Synopsis"]; 
cr["Synopsis"] = "Just testing..."; 

Events

In the J# APIs, events are exposed using the Java listener model. In the C# APIs, events are exposed using native .NET events.

The two models are significantly different in some respects. In .NET, an event handler is registered via an operator on the event object. There is no opportunity to provide additional parameters that describe an item type, the scope of interest, and so on.

For these reasons, the C# event APIs use the same basic event source model that was introduced in the StarTeam event APIs for COM. There is one EventSource type (such as, ItemEventSource) in the C# APIs for each listener interface (such as, ItemListener) in the J# APIs.

EventSource objects are created by factory methods defined in the relevant parent classes. For example, newItemEventSource() is a factory method defined in the View class (and also in the Folder class and the ItemListManager class) that returns an ItemEventSource. Where necessary, the factory methods take parameters that define the scope of interest.

For example, the following J# code that uses the J# APIs:

void listenForFilesAdded(View view) {
    Server s = view.getServer();
    Type type = s.typeForName(s.getTypeNames().FILE);

    // Register an event listener with the view.
    view.addItemListener(new ItemAdapter() { 

        // The event handler.
        public void itemAdded(ItemEvent e) { 
            File file = (File)e.getNewItem();
            System.out.println("File Added: " + file.getName());

        }, type); // The type parameter refines the scope.
}

would become the following C# code using the C# APIs:

void ListenForFilesAdded(View view) { 
    Server s = view.Server; 
    Type type = s.TypeForName(s.TypeNames.FILE); 

    // Create an event source via a factory method on the view.
    // The view and item type define the scope of interest.
    ItemEventSource source = view.NewItemEventSource(type); 

    // ItemEventSource exposes the OnItemAdded event (and others).
    // Attach an application event handler.
    // ItemEventSource.Handler is a delegate type.
    source.OnItemAdded += new ItemEventSource.Handler(OnFileAdded); 
} 

// The event handler.
private void OnFileAdded(ItemEventSource source, ItemEventArgs args) { 
    File file = (File)args.NewItem; 
    Console.WriteLine("File Added: " + file.Name); 
} 


Here, the ItemEventSource class exposes the OnItemAdded event (and others). It also defines the ItemEventSource.Handler delegate type, used for OnItemAdded event handlers. The client application's event handler takes two parameters: the ItemEventSource that triggered the event, and the ItemEventArgs that provides the event data.

Collections

In many cases where the J# APIs return an array of objects, the C# APIs return an instance of a StarTeam-specific collection class (for example, ProjectCollection, ItemCollection, and so on).

The collection classes are strongly typed, and implement the standard .NET IEnumerable, ICollection and IList interfaces. They are also modifiable, and support other common operations such as searching and sorting. For example:

// Collections are indexed by name, where appropriate.
p = server.Projects["StarDraw"]; 

// Collections can be sorted easily.
foreach (Label l in view.Labels.SortByID().Reverse()) { 
    . . . 
} 

The collection classes support implicit cast operators for converting to an array of objects. For example, a Borland.StarTeam.ItemCollection can be cast to a Borland.StarTeam.Item[].

However, there are memory management issues to consider. Casting to an array of objects in the C# namespace requires that C# wrapper objects exist for every member of the collection simultaneously. If you are simply iterating over the members of a large collection, it would be more efficient to use the standard .NET collection interfaces. For example:

// Allocates one C# wrapper object for every 
// member of the collection, simultaneously.
Borland.StarTeam.ItemCollection c;
Borland.StarTeam.Item[] items = c;
for (int i = 0; i < items.Length; i++) {
    Item item = items[i];
    . . .
} 

// Allocates one C# wrapper object at a time.
Borland.StarTeam.ItemCollection c;
foreach (Item item in c) { 
    . . . 
} 

Native .NET Types

The C# APIs use native .NET data types instead of Java data types, where applicable. For example, File.CheckoutToStream() takes a System.IO.Stream, rather than a java.io.OutputStream.

Some SDK types are also mapped to more appropriate .NET types. For example, OLEDate becomes System.DateTime; ItemList and Items both become ItemCollection.

Deprecated Classes

Classes and methods that were deprecated in the Java APIs prior to the release of the .NET SDK are missing from the C# APIs.

Writing Core/Edge .NET Applications

In this scenario, the application's core business logic is written in Java, and is cross-compiled to the .NET platform using Microsoft Visual J#. The core code uses the J# flavor of the StarTeam SDK APIs.

The user interface, or other .NET-specific edge code, is typically written in C# or Visual Basic .NET. The edge code uses the C# flavor of the StarTeam SDK APIs.

This is shown graphically in the figure below.

In order for this to work, the client application's edge code, written to the C# flavor of the StarTeam APIs, must be able to interoperate with the application's core code, written to the J# flavor of the APIs. For example, it must be possible for the edge code to create a Borland.StarTeam.Server object, and pass it to a method in the core code that requires a com.starbase.starteam.Server object.

Fortunately, the StarTeam SDK for .NET was explicitly designed to support this scenario. Interoperability between core and edge components is described in the following subsections.

Converting from Edge to Core

A StarTeam object from the C# namespace can be implicitly cast to the corresponding type in the J# namespace. For example:

Borland.StarTeam.Project p1; 
com.starbase.starteam.Project p2 = p1; 

Converting from Core to Edge

StarTeam classes in the C# world include a static Wrap() method that can be used to wrap the corresponding objects in the J# world. For example:

com.starbase.starteam.Project p1; 
Borland.StarTeam.Project p2 = Borland.StarTeam.Project.Wrap(p1); 

The Wrap() method hides details of the wrapping process from the client application. For example, Borland.StarTeam.Item.Wrap() might actually return a Borland.StarTeam.ChangeRequest object. Wrap() also handles null objects correctly.

Interface Adapters

Each interface defined in the SDK has a corresponding Adapter class that can convert from an instance of the interface in the C# world to an instance of the interface in the J# world, and vice versa. The adapter classes are public, and are available for use by client applications.

For example, to convert an instance of the ISecurableObject interface from the Borland.StarTeam namespace to the com.starbase.starteam namespace, you would use the ISecurableObjectAdapter, as follows:

Borland.StarTeam.ISecurableObject obj1;

com.starbase.starteam.ISecurableObject obj2 =
        = new Borland.StarTeam.ISecurableObjectAdapter(obj1);


Note that the adapters are bi-directional; thus, the following is also supported:

com.starbase.starteam.ISecurableObject obj1;

Borland.StarTeam.ISecurableObject obj2 =
        = new Borland.StarTeam.ISecurableObjectAdapter(obj1);

Java Adapters

Adapters are also available for some common Java data types. These can be found in the Borland.StarTeam.Util.JSharp namespace.

For example, to convert a java.io.InputStream to a System.IO.Stream, you would use the InputStreamAdapter, as follows:

java.io.InputStream s1;

System.IO.Stream s2 = 
        new Borland.StarTeam.Util.JSharp.InputStreamAdapter(s1);


Most, but not all, of the adapters for the Java data types are bi-directional.

Dynamic Type Conversion

When the actual type of an object is not known until runtime, dynamic type conversion services are available via static methods on the SDKWrapper class. For example:

// Convert a core object of unknown type
// from the J# world to the C# world.
object obj2 = SDKWrapper.Wrap(obj1); 

// Convert an edge object of unknown type
// from the C# world to the J# world.
object obj3 = SDKWrapper.Unwrap(obj2); 

 

These dynamic type conversion facilities work with SDK types, with objects that implement SDK interfaces, with Java classes for which there is an adapter implemented in the SDK, and so on. However, dynamic conversion is somewhat more expensive than the other mechanisms, and for that reason dynamic conversion should not be used in cases where the type is known at compile time.


Last Modified June 12, 2009