有没有办法使用类的文本名称将对象设置为新的类实例?
我将有一个类库,根据其他变量,我想在运行时获取其中一个类。
E.g。我有“CTest1”,“CTest2”,“CTest3”
我的功能类似于下面的
Function GetTestClass(lngClassNo as long) as Object
Dim strClassName as String
strClassName = "CTest" & CStr(lngClassNo)
Set GetTestClass = New instance of class(strClassName)
End Function
答案 0 :(得分:4)
VBA没有任何反映,所以我认为这是不可能的。你不得不做以下事情我害怕:
Function GetTestClass(lngClassNo as long) as Object
Select Case lngClassNo
Case 1
Set GetTestClass = New CTest1
Case 2
Set GetTestClass = New CTest2
...
End Select
End Function
除非你的CTest类是在COM DLL中定义的,否则你可以使用CreateObject语句。您需要使用VB6来创建这样的DLL,但是您无法在Excel,Access等中创建DLL。
Function GetTestClass(lngClassNo as long) as Object
Set GetTestClass = CreateObject("MyDll.CTest" & lngClassNo)
End Function
答案 1 :(得分:3)
你可以使用元编程来做到这一点,虽然看起来确实很糟糕。 下面是一个使用几个辅助函数的示例(为简洁起见省略):
Public Function CreateInstance(typeName As String) As Object
Dim module As VBComponent
Set module = LazilyCreateMPCache()
If Not FunctionExists(typeName, module) Then
Call AddInstanceCreationHelper(typeName, module)
End If
Dim instanceCreationHelperName As String
instanceCreationHelperName = module.name & ".GetInstanceOf" & typeName
Set CreateInstance = Application.Run(instanceCreationHelperName)
End Function
Sub AddInstanceCreationHelper(typeName As String, module As VBComponent)
Dim strCode As String
strCode = _
"Public Function GetInstanceOf" & typeName & "() As " & typeName & vbCrLf & _
"Set GetInstanceOf" & typeName & " = New " & typeName & vbCrLf & _
"End Function"
Call AddFunction(strCode, module)
End Sub
答案 2 :(得分:2)
VB类定义实际上是在幕后定义COM接口,因此可以使用implements关键字将数据类型定义为具有具体实现的抽象接口定义。
要获得任何类型的多态性,您必须这样做,否则您将遇到投射问题。使用VB执行此操作有点繁琐但技术上可行。如果你想深入了解Dan Appleman或Matthew Kurland的一些高级VB书籍。我不确定它们是否仍在印刷中,但它们可能通过亚马逊商城推出。
这适用于VB6,我相当确定它适用于VBA。
答案 3 :(得分:2)
嗨,我知道这是一个旧帖子,但如果你还需要答案,请看这里
http://www.codeproject.com/Articles/164036/Reflection-in-VBA-a-CreateObject-function-for-VBA
它应该回答你的问题。
答案 4 :(得分:0)
您可以使用集合类或对象数组来执行此操作。所有对象都在一个数组中。
在您的类中有一个.Name属性,当您创建它的实例时,请执行以下操作:
Dim CTest() as New CTest
For n = 1 to 10
Redim Preserve CTest(n)
CTest(n).Name = "CTest" & CStr(n)
Next l
快速而肮脏。上面的示例将在单个对象数组中返回10个CTest对象。您也可以放弃.Name并使用CTest(n)。
答案 5 :(得分:0)
CallByName
功能可以帮到你。我们假设项目中有一些类模块:clsSample0
,clsSample1
和clsSample2
。添加一个名为clsSpawner
的新类模块,它将所有目标类列为与e具有相同名称的公共变量。 G。 instance_
前缀,并使用New
关键字声明:
Public instance_clsSample0 As New clsSample0
Public instance_clsSample1 As New clsSample1
Public instance_clsSample2 As New clsSample2
在模块中添加Function Spawn()
代码:
Function Spawn(sClassName) As Object
Set Spawn = CallByName(New clsSpawner, "instance_" & sClassName, VbGet)
End Function
使用以下代码测试它:
Sub TestSpawn()
Dim objSample0a As Object
Dim objSample0b As Object
Dim objSample1 As Object
Dim objSample2 As Object
Set objSample0a = Spawn("clsSample0")
Set objSample0b = Spawn("clsSample0")
Set objSample1 = Spawn("clsSample1")
Set objSample2 = Spawn("clsSample2")
Debug.Print TypeName(objSample0a) ' clsSample0
Debug.Print TypeName(objSample0b) ' clsSample0
Debug.Print objSample0a Is objSample0b ' False
Debug.Print TypeName(objSample1) ' clsSample1
Debug.Print TypeName(objSample2) ' clsSample2
End Sub
它是如何工作的? Spawn
函数实例化clsSpawner
并调用clsSpawner
实例返回请求的属性,实际clsSpawner
实例由于{{1}声明而创建目标类的新实例} keyword并返回引用。