Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Basic: dynamically create objects using a string as the name

Tags:

object

vb.net

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

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
....

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()

In PHP, this is handled like so...

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

Edit: 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)

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?

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

like image 383
bob-the-destroyer Avatar asked Aug 07 '10 22:08

bob-the-destroyer


People also ask

How dynamically create an object in Java from a class name given as string format?

In order to dynamically create an object in Java from an inner class name, you should use the $ sign. For Example: String className = "MyTestClass"; String innerClassName = "MyInnerTestClass"; String fullPathOfTheClass = "full.

How do you create a dynamic object?

You can create custom dynamic objects by using the classes in the System. Dynamic namespace. For example, you can create an ExpandoObject and specify the members of that object at run time. You can also create your own type that inherits the DynamicObject class.

What can be used to create the object in VB?

The class is used to create objects. The objects are the cookies. You must create an object before you can access its members, except for Shared members which can be accessed without an object of the class.

Is Visual Basic dynamic?

Visual Basic binds to objects from the dynamic language runtime and dynamic languages such as IronPython and IronRuby by using the IDynamicMetaObjectProvider interface. Examples of classes that implement the IDynamicMetaObjectProvider interface are the DynamicObject and ExpandoObject classes.


2 Answers

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
like image 174
Tahbaza Avatar answered Oct 14 '22 04:10

Tahbaza


I'm pretty sure Activator is used for remoting. What you want to do is use reflection to get the constor and invoke it here's an example http://www.eggheadcafe.com/articles/20050717.asp

EDIT: I was misguided about Activator until jwsample corrected me.

I think the problem your having is that your assembly is the one that GetType is using to try and find Button. You need to call it from the right assembly.

This should do it

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"))
like image 40
Conrad Frix Avatar answered Oct 14 '22 05:10

Conrad Frix