在大多数情况下,可以在设计时发现对象的属性和方法,并编写代码来处理它们。 但是,在某些情况下,你可能事先不知道对象的属性和方法,或者你可能只想让最终用户在运行时指定属性或执行方法的灵活性。
CallByName 函数
例如,假设客户端应用程序通过将运算符传递给 COM 组件来评估用户输入的表达式。 假设你不断向需要新运算符的组件添加新函数。 使用标准对象访问技术时,必须先重新编译并重新分发客户端应用程序,然后才能使用新运算符。 为了避免这种情况,可以使用 CallByName
函数将新运算符作为字符串传递,而无需更改应用程序。
该 CallByName
函数允许使用字符串在运行时指定属性或方法。 函数的 CallByName
签名如下所示:
结果 = CallByName
(Object, ProcedureName, CallType, Arguments())
第一个参数 Object 采用要对其执行作的对象的名称。
ProcedureName 参数采用一个字符串,其中包含要调用的方法或属性过程的名称。
CallType 参数采用一个常量,该常量表示要调用的过程类型:方法(Microsoft.VisualBasic.CallType.Method
)、属性读取(Microsoft.VisualBasic.CallType.Get
)或属性集(Microsoft.VisualBasic.CallType.Set
)。
Arguments 参数(可选)采用一个类型Object
数组,其中包含该过程的任何参数。
可以将 CallByName
与当前解决方案中的类一起使用,但它最常用于访问 COM 对象或从 .NET Framework 程序集中访问对象。
假设您添加了一个对包含类MathClass
的程序集的引用,该类具有一个名为SquareRoot
的新函数,如以下代码所示:
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
应用程序可以使用文本框控件来控制将调用的方法及其参数。 例如,如果TextBox1
包含要计算的表达式,并且TextBox2
用于输入函数的名称,则可以使用以下代码在表达式中SquareRoot
调用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
如果在TextBox1
中输入“64”,在TextBox2
中输入“SquareRoot”,然后调用CallMath
过程,就会计算TextBox1
中的数字的平方根。 示例中的代码调用 SquareRoot
函数(该函数接受一个字符串作为必需参数,该字符串包含需要计算的表达式),并在 TextBox1
返回“8”(即 64 的平方根)。 当然,如果用户输入无效的字符串, TextBox2
如果字符串包含属性的名称而不是方法,或者该方法具有额外的必需参数,则会发生运行时错误。 在使用 CallByName
时,必须添加可靠的错误处理代码,以预测这些或任何其他错误。
注释
虽然在某些情况下,CallByName
函数可能很有用,但必须将其有用性与性能影响进行权衡——使用 CallByName
来调用过程比后期绑定调用要慢一些。 如果要调用重复调用的函数(例如循环内部), CallByName
可能会对性能产生严重影响。