Instantiating and obtaining instances of .NET classes
For most .NET class types, you can instantiate the class exactly as you do an ABL user-defined class, by defining a variable or parameter as the given class type and using the NEW function (classes) to invoke a constructor of the class. For example:
DEFINE VARIABLE rList AS CLASS System.Collections.Generic.SortedList NO-UNDO.
rList = NEW System.Collections.Generic.SortedList( ).
As when creating any ABL user-defined class instance, ABL creates this .NET SortedList object using its default constructor and adds the instance to the session object chain, because in ABL, all ABL object instances, including .NET ones, are also instances of Progress.Lang.Object (see Incorporation of the .NET object model).
You can also obtain an instance of a class created by .NET and assign its object reference to an ABL data item, which also adds the instance to the ABL session object chain. This occurs in the following cases:
When you access a .NET property or data member that returns a reference to an object created by .NET and assign this object reference to an ABL data item. For more information on accessing .NET properties and data members, see Accessing .NET class members.
When you pass an ABL data item as an argument to a .NET output method parameter that returns (and "assigns" to the data item) the object reference of an object created by .NET. For more information on passing .NET method parameters, see Specifying .NET constructor and method parameters.
When you access the event parameters from within an ABL handler for .NET events, which always passes an input System.EventArgs object reference that is created by .NET. There is also an input System.Object parameter, but you usually already have an object reference to this object, which doesn't need to be added to the session object chain. For more information on using ABL methods and procedures as .NET event handlers, see Handling .NETevents.
For example, the Location property in this code fragment returns a reference to a .NET System.Drawing.Point object created by .NET for a button control and assigns this object reference to an ABL variable (rLocation) that is defined to hold that object reference:
DEFINE VARIABLE rLocation AS CLASS System.Drawing.Point NO-UNDO.
DEFINE VARIABLE rButton AS CLASS System.Windows.Forms.Button NO-UNDO.
rButton = NEW System.Windows.Forms.Button( ).
/* Add button to a form */
...
rLocation = rButton:Location.
However, you can create or obtain a .NET object whose reference does not appear on the ABL session object chain. This happens when the object reference for the .NET object that you create or access is:
Assigned directly to another .NET property or field (data member)
Passed directly to an INPUT parameter of a .NET method
Used directly in an ABL expression (as in a MESSAGE statement) or otherwise never stored in an ABL data element
Note: You cannot pass an object reference to a public .NET property or data member as an OUTPUT or INPUT-OUTPUT parameter to a .NET method, because ABL syntax does not allow the required colon (:) notation for passing parameters in these access modes. So, you cannot set a .NET property or data member object reference value in this way.
For example, this code fragment instantiates a .NET System.Drawing.Size object and assigns its object reference directly to the Size property of a .NET button object:
DEFINE VARIABLE rButton AS CLASS System.Windows.Forms.Button NO-UNDO.
ASSIGN
rButton = NEW System.Windows.Forms.Button( )
rButton:Size = NEW System.Drawing.Size(80, 40).
In other words, the System.Drawing.Size object created by the code fragment is never stored as an ABL object reference. In all cases where you create or return existing .NET objects from .NET that you assign or pass directly back to .NET, .NET handles all garbage collection for such objects. (see .NET class instances and garbage collection).
Note that when you invoke a .NET class constructor or method that takes parameters defined as a .NET mapped data type, ABL requires that you pass arguments defined as the corresponding ABL primitive types. In other words, you cannot define and pass a .NET System.Int32 to parameter defined as a System.Int32, but must pass an ABL INTEGER instead. Otherwise, if the parameter is defined as an unmapped .NET object type (such as System.Drawing.Size), you can pass an instance of that object type directly to the parameter.
For example, for the SortedList constructor that takes a .NET System.Int32 parameter, you can instantiate the .NET class by passing an ABL INTEGER value:
DEFINE VARIABLE rList AS CLASS System.Collections.Generic.SortedList NO-UNDO.
rList = NEW System.Collections.Generic.SortedList(5).
For more information on passing .NET parameters, see the information on accessing .NET methods in Accessing .NET class members. For more information on working with .NET data types in ABL, see Using.NET data types in ABL.
To create one supported set of class types—array objects—you must use a completely different mechanism for creating class instances for them. All .NET array objects derive from the .NET base class, System.Array. To instantiate and perform basic operations on array objects, you must use members of the System.Array base class. For more information on the instantiation and management of array objects, see Accessingand using .NET arrays.