Visual Basic: динамически создавать объекты, используя строку в качестве имени - PullRequest
5 голосов
/ 08 августа 2010

Есть ли способ динамически создать объект, используя строку в качестве имени класса?

Я отключен от VB уже несколько лет, но для решения проблемы на другом языке я вынужденразработать обертку в этом.У меня есть фабричный метод для динамического создания и возврата объекта типа на основе входных данных из других источников.Предоставленный ввод должен быть именем класса, из которого создается объект.Обычный синтаксис означает, что весь класс должен быть явно прописан.Чтобы сделать это таким образом, буквально могут быть сотни if / then или case для обработки всех доступных вариантов классов / объектов в ссылочных библиотеках:

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

Я надеюсь вместо этого уменьшить все это делообработка в одну строку: IE ...

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

В PHP это обрабатывается так ...

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

Редактировать: Глядя на некоторыеиз ответов, я думаю, что я в пути над моей головой здесь.Мне удалось заставить его работать, используя это изменение метода CreateInstance класса Assembly, хотя меня больше интересует это изменение, дающее больше опций , включая предоставление параметров конструкции ...

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)

Другими словами, для этого нужен метод, а не какой-либо синтаксис языка? Этот вариант Activator также работал при использовании полной строки сборки и пути к классам.Я подозреваю, что CreateInstance может не иметь полной возможности разрешать мне обрабатывать объекты, как если бы они были вызваны нормально, то есть obj = new System.Windows.Forms.Button.Вот почему я не могу просто использовать CreateObject.Если нет функции естественного языка, позволяющей заменить имя класса на строку, кто-нибудь знает, какие ограничения можно ожидать от использования CreateInstance?

Кроме того, есть ли разница?между базовыми методами Activator.CreateInstance (после развертывания) и Assembly.CreateInstance?

Ответы [ 4 ]

10 голосов
/ 08 августа 2010

Скорее всего, это будет делать то, что вы хотите / проверено работает;переключите комментарий типа сверху, чтобы увидеть.

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
3 голосов
/ 08 августа 2010

Я почти уверен, что Активатор используется для удаленного взаимодействия. То, что вы хотите сделать, это использовать отражение, чтобы получить констор и вызвать его, вот пример http://www.eggheadcafe.com/articles/20050717.asp

РЕДАКТИРОВАТЬ: я ошибался насчет активатора, пока jwsample не исправил меня.

Думаю, проблема в том, что ваша сборка - это та, которую использует GetType, чтобы попытаться найти Button. Вам нужно позвонить из правильной сборки.

Это должно сделать это

Dim asm As System.Reflection.Assembly = System.Reflection.Assembly.LoadWithPartialName("System.Windows.Forms")


Dim obj As Object = Activator.CreateInstance(asm.GetType("System.Windows.Forms.Button"))
0 голосов
/ 04 марта 2016

Вот очень простой способ, который я нашел, роясь в интернете:

dynamicControl = Activator.CreateInstance(Type.GetType("MYASSEMBLYNAME." + controlNameString))
0 голосов
/ 08 августа 2010

Посмотрите на метод Activator.CreateInstance (Type).

Если вы вводите имя класса, вы должны сделать это:

Dim obj As Object = Activator.CreateInstance(GetType("Name_Of_Your_Class")) 

Вам придется возиться с вызовом GetType, чтобы убедиться, что вы предоставили ему достаточно информации, но в большинстве случаев должно работать только имя класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...