使用字符串名称调用属性或方法 (Visual Basic)

在大多数情况下,可以在设计时发现对象的属性和方法,并编写代码来处理它们。 但是,在某些情况下,你可能事先不知道对象的属性和方法,或者你可能只想让最终用户在运行时指定属性或执行方法的灵活性。

CallByName 函数

例如,假设客户端应用程序通过将运算符传递给 COM 组件来评估用户输入的表达式。 假设你不断向需要新运算符的组件添加新函数。 使用标准对象访问技术时,必须先重新编译并重新分发客户端应用程序,然后才能使用新运算符。 为了避免这种情况,可以使用 CallByName 函数将新运算符作为字符串传递,而无需更改应用程序。

CallByName 函数允许使用字符串在运行时指定属性或方法。 函数的 CallByName 签名如下所示:

结果 = CallByNameObjectProcedureNameCallTypeArguments())

第一个参数 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 可能会对性能产生严重影响。

另请参阅