Dynamically invoke a method at run time
- Last Updated: March 30, 2020
- 5 minute read
- OpenEdge
- Version 12.2
- Documentation
Syntax
Traditional class-based programming in ABL assumes that classes and their members are strongly typed at compile time. The AVM verifies the type and validity of class-based objects and class-based object references when the class is compiled.
There might be points in your
application where the name of the class and the parameters to be
passed to it are only known at run time. You can use either the
built-in DYNAMIC-INVOKE function or the Invoke( ) method
of the Progress.Lang.Class class to dynamically
invoke a class-based method at run time.
DYNAMIC-INVOKE is
a built-in ABL function that invokes a class-based method whose
name is specified by a run-time expression, but whose parameters
are defined at compile time. DYNAMIC-INVOKE takes
an instance of an object, and an expression for the method name
to be invoked, followed by a fixed list of compile-time, bound parameters.
Consistent with the functionality provided by the DYNAMIC-NEW statement, DYNAMIC-INVOKE fully
supports method overloading.
The Invoke( ) method
of the Progress.Lang.Class class provides similar
functionality to DYNAMIC-INVOKE. The advantage
to the latter is that it has a fixed, compile-time parameter list
and does not require the creation of a Progress.Lang.ParameterList object
at run time. For more information about the Progress.Lang.ParameterList class,
see ABL Reference and Use the Progress.Lang.ParameterList class.
DYNAMIC-INVOKE does not operate
on built-in classes. This is analogous to the DYNAMIC-FUNCTION function
and the DYNAMIC-NEW statement, which also do not
operate on built-in classes.
DYNAMIC-INVOKE can
invoke either void or non-void, class-based methods. When invoking
a non-void method, the caller can capture the returned value by
assigning DYNAMIC-INVOKE to an expression of an
appropriate type. This assignment operation follows the existing
rules for assigning the return value of a method to an expression.
If the caller chooses, the program does not need to capture the
returned value. In contrast, when invoking a void method, the caller
must not attempt to assign the method return value to an expression—doing
so will cause the AVM to generate a run-time error. When invoking
a void method with DYNAMIC-INVOKE, it is only permissible
to do so with code that does not expect a return value.
This
is the syntax for the DYNAMIC-INVOKE function:
|
The DYNAMIC-INVOKE function
accepts either a class type name or an object reference. A class
type name is specified when the method to be invoked is static.
An object reference is used to identify the object on which the
method invocation is to occur.
In this example, the FooDec( ) method
in the class instance referenced by rObj expects
a DECIMAL value. With data type widening support,
an ABL DECIMAL, INTEGER, or INT64 value
can be passed to this method:
|
You can use the Invoke( ) method
of the Progress.Lang.Class class to invoke a method when
the method name and any parameters are only known at run time. This method
returns an optional data element which is assigned the return value from
the invoked, non-void method. This data element can be any data
type. The AVM checks the return value at run time for data type
compatibility with what is actually returned by the method.
The Invoke( ) method
is one of several reflection methods of the Progress.Lang.Class class
that provide type information about a class or interface at run
time. For more information about the reflection capabilities of
the Progress.Lang.Class class, see Use the Progress.Lang.Class class.
The Invoke( ) method
has four overloaded constructors. You can use the first version
to invoke a class-based static or instance method that does not
take any parameters. This is the syntax for using this version of
the Invoke( ) method:
|
You can use the second overloaded version to
invoke a class-based method that takes zero or more parameters.
The parameter list is passed as a Progress.Lang.ParameterList object.
This is the syntax for using this version of the Invoke( ) method:
|
You can use the third overloaded version to
invoke a static method that does not take any parameters (see the ).
This is the syntax for using this version of the Invoke( ) method:
|
You can use the fourth overloaded version to
invoke a static method that takes zero or more parameters (see the ).
The parameter list is passed as a Progress.Lang.ParameterList object.
This is the syntax for using this version of the Invoke( ) method:
|
Element descriptions for these syntax diagrams follow:
- data-element
- An optional ABL data element which is assigned the return value from the invoked, non-void method. This data element can be any ABL data type that is compatible with the return value data type.
- class-reference
- An object reference for the
Progress.Lang.Classinstance containing the type information. - object-reference
- A reference to the object that contains the method you want
to invoke, and whose type is compatible with the class-reference object.
When invoking a static method, the
Unknown value (?)is passed for this parameter. - method-name
- A
CHARACTERexpression that evaluates at run time to the name of the method to be invoked. - parameterlist-object
- An instance of the
Progress.Lang.ParameterListclass. Since aProgress.Lang.ParameterListobject can be built with zero or more parameters, this version of theInvoke( )method can be used to invoke any method, even if it does not take any arguments. See Use the Progress.Lang.ParameterList class for a list of common public properties and methods of theProgress.Lang.ParameterListclass.
DYNAMIC-INVOKE function and
the Invoke( ) method of the Progress.Lang.Class class
provide similar functionality. They differ in that the former requires
a fixed, compile-time parameter list, while the latter requires
a instantiated and populated run-time Progress.Lang.ParameterList object.The
following example shows the Invoke( ) method
overloading to call an instance method without parameters. It gets
the MyClass class type using the GetClass( ) method
of the Progress.Lang.Class class. An instance of
this class type is created using the New( ) method
of Progress.Lang.Class and casting the Progress.Lang.Object result
to a MyClass object reference, which is then assigned
to rObj. Invoke( ) then
calls the MyDynMethod( ) method, specified
as a character string, in rObj without parameters:
|
The following example shows the Invoke( ) method
overloading to call an instance method with parameters. It creates
an instance of MyClass class assigned to rObj.
The rParamList object, an instance of the Progress.Lang.ParameterList class,
holds the parameter data. The parameter data is passed to the MyDynMethod( ) method
when it is invoked in the rObj object:
|
The following example shows the Invoke( ) method
overloading to call a static method without parameters. In this
case, Invoke( ) is called directly on
the instance of Progress.Lang.Class that is returned
from GetClass( ) for the MyClass type,
which allows it to invoke the specified static MyStaticMethod( ) method
on that type:
|
The following example shows the Invoke( ) method
overloading to call a static method with parameters. Again, Invoke( ) is
called on a Progress.Lang.Class instance representing
the MyClass type, which allows it to invoke the
static MyStaticMethod( ) method, this
time, with the parameter list specified by rParamList:
|