Calling a Property or Method Using a String Name
In most cases, you can discover the properties and methods of an object at design time, and write code to handle them. In a few cases, however, you may not know about an object's properties and methods in advance, or you may simply want the flexibility of allowing an end user to specify properties or execute methods at run time.
Consider, for example, a client application that evaluates expressions entered by the user by passing an operator to a COM component. Suppose you are constantly adding new functions to the component that require new operators. Using standard object access techniques, you would need to recompile and redistribute the client application before it could use the new operators. To avoid this, you can use the CallByName function to pass the new operators as strings, without changing the application.
The CallByName function allows you to use a string to specify a property or method at run time. The signature for the CallByName function looks like this:
Result = CallByName(Object, ProcedureName, CallType, Arguments())
The first argument, Object, takes the name of the object you want to act upon. The ProcedureName argument takes a string containing the name of the method or property procedure to be invoked. The CallType argument takes a constant representing the type of procedure to invoke: a method (Microsoft.VisualBasic.CallType.Method), a property read (Microsoft.VisualBasic.CallType.Get), or a property set (Microsoft.VisualBasic.CallType.Set). The Arguments argument, which is optional, takes an array of type Object containing any arguments to the procedure.
You can use CallByName with classes in your current solution, but it is most often used to access COM objects or objects from .NET Framework assemblies.
Suppose you add a reference to an assembly that contains a class named MathClass, which has a new function named SquareRoot, as shown in the following code:
Class MathClass Function SquareRoot(ByVal X As Double) As Double Return Math.Sqrt(X) End Function Function InverseSine(ByVal X As Double) As Double Return Math.Atan(X / Math.Sqrt(-X * X + 1)) End Function Function Acos(ByVal X As Double) As Double Return Math.Atan(-X / Math.Sqrt(-X * X + 1)) + 2 * Math.Atan(1) End Function End Class
Your application could use text box controls to control which method will be called and its arguments. For example, if TextBox1 contains the expression to be evaluated, and TextBox2 is used to enter the name of the function, you can use the following code to invoke the SquareRoot function on the expression in TextBox1:
Private Sub CallMath() Dim Math As New MathClass Me.TextBox1.Text = CStr(CallByName(Math, Me.TextBox2.Text, _ Microsoft.VisualBasic.CallType.Method, TextBox1.Text)) End Sub
If you enter "64" in TextBox1, "SquareRoot" in TextBox2, and then call the CallMath procedure, the square root of the number in TextBox1 is evaluated. The code in the example invokes the SquareRoot function (which takes a string containing the expression to be evaluated as a required argument) and returns "8" in TextBox1 (the square root of 64). Of course, if the user enters an invalid string in TextBox2, if the string contains the name of a property instead of a method, or if the method had an additional required argument, a run-time error occurs. You need to add robust error-handling code when you use CallByName to anticipate these or any other errors.
While the CallByName function may be useful in some situations, you need to weigh its usefulness against the performance implications — using CallByName to invoke a procedure is slightly slower than a late-bound call. If you are invoking a function that is called repeatedly, such as inside a loop, CallByName can have a severe effect on performance.