Visual Basic:使用字符串作为名称动态创建对象

Visual Basic:使用字符串作为名称动态创建对象

问题描述:

有没有办法使用字符串作为类名动态创建对象?

Is there a way to dynamically create an object using a string as the class name?

我已经离开 VB 好几年了,但是为了用另一种语言解决问题,我不得不用这种语言开发一个包装器.我有一个工厂方法,可以根据其他地方的输入动态创建和返回一个类型的对象.提供的输入是用来创建对象的类名.正常语法意味着必须明确说明整个类.要这样做,实际上可能有数百个 if/then 或 case 来处理引用库中所有可用的类/对象选择:

I've been off VB for several years now, but to solve a problem in another language, I'm forced to develop a wrapper in this one. I have a factory method to dynamically create and return an object of a type based on input from elsewhere. The provided input is meant to be the class name from which to create an object from. Normal syntax means that the entire class has to be explicitly spelled out. To do it this way, there could literally be hundreds of if/then's or cases to handle all the available class/object choices within the referenced libs:

If c_name = "Button" then obj = new System.Windows.Forms.Button
If c_name = "Form" then obj = new System.Windows.Forms.Form
....

我希望将所有这些案例处理减少到一行:IE...

I'm hoping instead to reduce all this case handling to a single line: IE...

my_class_name = "whateverclass"
obj = new System.Windows.Forms.my_class_name()

在 PHP 中,这是这样处理的...

In PHP, this is handled like so...

$my_class_name = "whateverclass";
$obj = new $my_class_name();

看了一些答案,我觉得我有点不知所措.我确实设法使用 this CreateInstance 程序集的方法变体使其工作类,尽管我对这种变体提供更多选择更感兴趣, 包括提供构造参数...

Looking at some of the answers, I think I'm in way over my head here. I did manage to get it working using this CreateInstance method variation of the Assembly class, even though I'm more interested in this variation giving more options, including supplying construct parameters...

my_type_name = "System.Windows.Forms.Button"
asmb_name = "System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
button1 = Reflection.Assembly.Load(asmb_name).CreateInstance(my_type_name)

换句话说,它需要一种方法来做到这一点,而不是任何固有的语言语法?此激活器变体在使用完整程序集字符串和类路径时也有效.我怀疑 CreateInstance 可能没有完全的能力让我将对象视为正常调用,即 obj = new System.Windows.Forms.Button.这就是为什么我不能简单地使用 CreateObject.如果没有允许您用类名替换字符串的自然语言功能,有没有人知道使用 CreateInstance 会带来什么样的限制?

In other words, it takes a method to do this, and not any inherent language syntax? This Activator variation also worked when the full assembly string and class path is used. I'm suspicious CreateInstance may not have the full ability to let me treat objects as if they were called normally, ie obj = new System.Windows.Forms.Button. This is why I can't use simply CreateObject. If there is no natural language feature allowing you to substitute a class name for a string, does anyone have any insight into what sort of limitations I can expect from using CreateInstance?

此外,基本的 Activator.CreateInstance(在 Unwrap 之后)和 Assembly.CreateInstance 方法之间甚至有区别吗?

Also, is there even a difference between basic Activator.CreateInstance (after Unwrap) and Assembly.CreateInstance methods?

这可能会做你想要/测试的工作;切换顶部的类型注释即可查看.

This will likely do what you want / tested working; switch the type comment at the top to see.

Imports System.Reflection

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    '            Dim fullyQualifiedClassName as String = "System.Windows.Forms.TextBox"
    Dim fullyQualifiedClassName As String = "System.Windows.Forms.Button"
    Dim o = fetchInstance(fullyQualifiedClassName)
    ' sometime later where you can narrow down the type or interface...
    Dim b = CType(o, Control)
    b.Text = "test"
    b.Top = 10
    b.Left = 10
    Controls.Add(b)
End Sub

Private Function fetchInstance(ByVal fullyQualifiedClassName As String) As Object
    Dim nspc As String = fullyQualifiedClassName.Substring(0, fullyQualifiedClassName.LastIndexOf("."c))
    Dim o As Object = Nothing
    Try
        For Each ay In Assembly.GetExecutingAssembly().GetReferencedAssemblies()
            If (ay.Name = nspc) Then
                o = Assembly.Load(ay).CreateInstance(fullyQualifiedClassName)
                Exit For
            End If
        Next
    Catch
    End Try
    Return o
End Function