PowerBuilder's .NET Strategy

.NET has become a mainstream programming platform. To be in line with PowerBuilder's .NET strategy (.NET deployment and .NET development), PB11 introduced many .NET-related features:

These language features are a major step on PB's roadmap to providing support for .NET platform, however they are relatively isolated and have some limitations, such as:

Meanwhile, the .NET Framework is becoming more and more powerful, the .NET Framework class library is expanding with each new release, and more useful features have been introduced in the latest version of .NET Framework 3.5.

In PB12, the PowerScript language is supposed to be a CLS-compliant .NET language that can easily interoperate with other .NET CLS-compliant languages. Users will be able to consume and extend any CLS-compliant .NET resources thereby saving them a lot of development time.

On the other hand, more modern language features will be brought into PowerScript as well. These features will be delivered in a 4GL manner to maintain PB's productivity and bring PowerScript's differentiators to other .NET languages. The original PowerBuilder object model will be kept as much as possible to minimize the learning curve and preserve customers' investment, knowledge, and skills in PowerBuilder.

Why should PowerScript be a CLS-compliant .NET language? What is CLS? Simply put, CLS is a set of rules intended to promote language interoperability. Language interoperability means some code written in one language can interact with other code written in another language. Language interoperability can help maximize code reuse and, therefore, improve the efficiency of the development process.

In the current market, developers use varied programming languages to develop their applications. Each of them may support different features and types, so the language interoperability is hard to achieve. However, any .NET language that targets the .NET Common Language Runtime (CLR) will benefit from its built-in support for language interoperability. CLR specifies and enforces a common type system (CTS) for all .NET languages, which means each of them must follow CTS rules to define and use types. The usage of types is consistent across .NET languages; since all type information is stored and retrieved in the same way, the CLR can execute multiple languages in one .NET application.

But there is still some barrier in .NET language interoperability, because each .NET language uses CTS to support its own unique set of language features. There is no guarantee that the calling code written in one language can be fully accessed by the caller language. For example, if one language provides support for unsigned integers, you can design a field with type UInt16; but from a .NET language that has no concept of unsigned integers, that field won't be useful.

To ensure that the component developed in one .NET language can be fully accessible to any other .NET languages, the .NET Framework provides a Common Language Specification (CLS) that describes a set of features commonly needed by any .NET language. In other words, it defines the minimum language requirements that must be supported by any .NET language.

Therefore, to make PowerScript a .NET language, we must ensure that it is CLS-compliant.

In CLS terminology, there are three different roles: framework, consumer, and extender.

The detail information can be referred to as the Common Language Infrastructure (CLI) Partition I.

In PB12, the PB .NET assembly/Web Service will be targeted as the CLS Framework. PB's classic IDE will be targeted as the CLS consumer. The new WPF workshop IDE will be targeted as the CLS-compliant extender that lets users consume and extend the .NET CLS Framework and produce PB's own CLS Framework (PB .NET assembly/Web Service) for consumption by other .NET languages.

Figure 1 shows the relationship among CTS, CLS, and various .NET languages. As you can see, all .NET languages fully support CLS features and partially support their own set of CTS features. They have some common features, but they all have their own unique features as well.

In terms of the language interoperability in PB12 PowerScript will be CLS-compliant, which means that PowerScript will be able to consume and extend any CLS-compliant resources produced by other .NET languages and produce PB .NET assemblies/Web Services as CLS-compliant component.

The non-CLS-compliant .NET resources will be considered to be consumed or extended case-by-case. For example if the resource only involves unsigned integer types that are not CLS-compliant types, PB will be able to support it.

On the other hand, since PowerScript has its own unique set of language features, many of them are not CLS-compliant, therefore, the overall functionality of PowerScript will go beyond CLS rules, and PB .NET target applications (Windows Forms, Web Forms, or WPF) don't have to be CLS-compliant, users can use any language feature to develop their .NET applications.

As we all know, System.Object type is the root type of all .NET types. In PB12, the type system of PowerScript will be enhanced. All PB primitive types will be equivalent to their corresponding .NET primitive types, and the functionality of the .NET Sytem.Enum type and the .NET System.Array type will be merged with that of the PB enum type and PB array type, respectively. The PB PowerObject type will also inherit from .NET System.Object type. Finally System. Object type will be the root type of all PB types as well.

In .NET, an interface defines a contract. A class that implements an interface must adhere to its contract. In PB12, users will be able to define their own interfaces, which can include methods, properties, events, and indexers. The new syntax is as follows:

global type ISub1 interface [from IBase1, IBase2]
//Functions
function string MyFunction(integer i)
subroutine MySub(string s)
//Properties
integer Myproperty1 [get, set]
integer Myproperty2 [set]
string Myproperty3[get]
//Events
event type integer MyEvent ( )
//Indexers
string this[integer i, integer j] [get, set]
end type

The PB object types Custom Class, Standard Class, Custom Visual, Standard Visual, Window, and Menu will be able to implement both user-defined PB interfaces and imported .NET interfaces.

Currently in PB, an unbounded array must be single-dimensional, which means the array-bound information of a multi-dimensional array must be specified at compile time. This limitation prevents users from declaring a multi-dimensional array without specifying the array-bound information and assigning another array to it at runtime, which is a pretty common scenario in .NET programming. For example, a Web Service may return a multi-dimensional array, whose size is unknown at compile time.

In PB12, a single-dimensional array will be enhanced so it can be dynamically created. For example, int arr[] which is an unbounded single-dimensional integer array.

At runtime, users can create a single-dimensional array as follow:

arr = create int[2 to 5]

which creates a single -dimensional integer array, with indexes of the one dimension being 2 to 5.

A multi-dimensional array will be enhanced to be declared without specifying the array bounds. For example, int arr[,] which is a two-dimensional integer array.

At runtime, users can create a multidimensional array as follows:

arr = create int[4, 2 to 5]

which creates a two-dimensional integer array, with indexes of the two dimensions being 1 to 4 and 2 to 5.

Jag-array will be allowed to be declared. For example, int arr[][], which is a integer jag-array.

At runtime, users can create a jag-array as follow:

arr = create int[3][]
arr[1] = create int[5]
arr[2] = create int[20]
arr[3] = create int[10]

The first line creates an array with three elements, each of type int[] . The subsequent lines then initialize the three elements with references to individual array instances of varying lengths.

In .NET, a delegate type represents references to methods with a particular parameter list and return type. Delegates are similar to the concept of function pointers in some languages, such as C, but unlike function pointers, delegates are object-oriented and type-safe. In PB12, users will be able to make use of the .NET delegate type to cooperate with native PowerScript code.

The following example declares and uses a delegate type named Function in an imported .NET assembly.

.NET delegate declaration in C#:

delegate double Function(double x);

Consuming this delegate type in PowerScript:

public function double[] Apply ((double a[], Function f)
double result[]
for i = 0 to i < a.Length step 1
result[i] = f(a[i])
next
return result
end function
public function double Multiply(double x)
return x * factor;
end function
public function test()
double a[] = {1.0,2.0,3.0,4.0,5.0}
double doubles[] = Apply(a, Multiply)
end function

In PB12, the standard NVO will be able to inherit from a .NET class, which will override all virtual and abstract methods, properties, indexers, and events defined in the .NET base class and implemented interfaces.

Table 1 provides an overview of the kinds of members of a .NET class that can be exposed in PB.

This syntax of calling PowerScript functions and events will also be used to call the functions and events of .NET class as follow:

{ objectname.} { type } { calltype } { when } name ( { argumentlist } )

In .NET, generics are classes, structures, interfaces, and methods that have placeholders (type parameters) for one or more of the types that they store or use.

A generic collection class might use a type parameter as a placeholder for the type of objects that it stores; the type parameters appear as the types of its fields and the parameter types of its methods. A generic method might use its type parameter as the type of its return value or as the type of one of its formal parameters. In PB12, users will be able to consume .NET generic classes and methods, if they conform to generic CLS rules. But defining a generic type and overriding a generic method won't be supported.

Here's an example of consuming generic type in PB:

System.Collections.Generic.SortedList<string, integer> teams
teams = create System.Collections.Generic.SortedList<string, integer>
teams["DEV"] = 30
teams["QA"] = 25

In PB12, users will be able to define a global enum type; the new enum painter will be similar to Structure Painter as shown below.

To define a local enum, users will have to open the object painter that has a local enum painter attached.

The following kinds of PB objects will be able to define local enum: Custom Class, Standard Class, Custom Visual, Standard Visual, Window, and Menu.

In PB12, the following kinds of PB objects will be able to specify which namespace the object group belongs to and which namespaces the object group is using: Custom Class, Standard Class, Custom Visual, Standard Visual, Window, Menu, Structure, Function, Interface, and Enum.

There are two ways to identify a unique name. The first one is to use qualified names. That's a namespace name followed by the scope-resolution operator (.) and then the name of either a nested namespace or a group and the name of a member of a group. For example:

MyPkg.MyNestedPkg.w_main`cb_1

The second way is to use a using directive:

Using pkg1[.pkg2[.pkg3]...]

A using directive allows a named type to be referred to by a simple name that consists of a single identifier.

Currently in PB, a default constructor event is used to instantiate object. When a PB NVO object is created at runtime, an auto-generated oncreate event will be triggered in which the default constructor event will be subsequently triggered.

But the default constructor event doesn't support overloading so it will lose its flexibility to instantiate and initialize a particular type of object.

In PB12, parameterized constructor events will be supported, but they will only apply to custom and standard NVO types.

The syntax will be as follows:

objectvariable = create objecttype[(arg1[,arg2]...)]

In .NET, the custom attribute is a class used to represent custom metadata.

In PB12, users will be able to define a custom attribute class, but only some .NET types and their corresponding PB types can be useable as an attribute parameter type.

The syntax will be enhanced to support defining and applying custom attributes as follow:

global type EventPrototype from System.Attribute usage [event]
end type
type variables
public string prototype
end variables
forward prototypes
subroutine EventPrototype(string prototype)
end prototypes
subroutine EventPrototype(string pt)
prototype = pt
end subroutine

[EventPrototype("pbm_lbndblclk")]
event clicked
end event

© 2008 SYS-CON Media