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

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

CallByName 函数

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

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

Result = 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 用于输入函数的名称,则你可以使用以下代码对 TextBox1 中的表达式调用 SquareRoot 函数:

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 可能会对性能造成严重影响。

另请参阅