0

I have database table which has a field called "datatype". It will hold a particular datatype, such as string, integer, classname, etc....

How can I dim a variable using whatever is stored in this field? For example, if the field says "string" I want to effectively say "Dim MyVar as string", but fill in the "string" portion with what's stored in the table. Hope that makes sense. Thanks!

WebDevGuy
  • 173
  • 4
  • 18
  • the column might be named "datatype" but what is **its** datatype? String? – Ňɏssa Pøngjǣrdenlarp Oct 20 '14 at 17:42
  • While retrieving the result , you need to create different variables based on `type`, because you can not have `MyVar` as string and at same time as integer. – Arindam Nayak Oct 20 '14 at 17:45
  • What happens when someone hacks your db? `Dim MyVar as urmomlolz` Hopefully you will be using a whitelist. ;) – The Blue Dog Oct 20 '14 at 17:45
  • I suspect this is a portion of a roll your own TypeConverter (which leads one to wonder how the data portion is stored). – Ňɏssa Pøngjǣrdenlarp Oct 20 '14 at 17:47
  • Why would you want to do this kind of thing? at least explain the motivation... – ilans Oct 20 '14 at 18:03
  • Thanks everyone for your feedback. Good info! Yes, the datatype field is a string. The situation is complicated. Basically we using Docentric to dynamically creating Word documents, which will be based on a number of pre-defined Word/Docentric templates. Each template's datasource is based on a different class. In my VB.NET code I need to pass the correct datasource in when generating the document. So, in the db if the record for "MyTemplate1.docx" is based on MyClass then "MyClass" would be in the "datatype" field. Sorry, I know that's confusing. – WebDevGuy Oct 20 '14 at 18:18
  • Do you need to create an instance of `MyClass` from the string name? Or can you get by with just the Type? – djv Oct 20 '14 at 18:22
  • @Verdolino - My variable can be several datatypes, such as.... string, MyClass1, MyClass2, etc... Hopefully that makes sense. – WebDevGuy Oct 20 '14 at 21:47
  • I still don't know if you want an instance or an empty Dim. Say you have a class `MyClass1`. Does your code require `Dim o As New MyClass1()` or just `Dim o As MyClass`? Does "String" really need to resolve to a string or was that just a hypothetical example? – djv Oct 20 '14 at 22:39
  • @Verdolino - Yes, it will always be a class in this case. So, for example, any of these are possible.... Dim X as new MyClass1(), Dim X as new MyClass2(), etc... "MyClass1" will be what's in the db field. Thanks! – WebDevGuy Oct 21 '14 at 13:38

1 Answers1

1

You can create instances from the name of the class. Note, you can't ask for "MyClass1" without the namespace before it. There are some options for getting from "MyClass1" to "Namespace.MyClass1" such as a Dictionary or even putting the full type name in your database.

Module Module1
    Sub Main()
        ' compiler knows mc1 is a IMyClasses
        Dim mc1 = CType(getInstanceFromTypeName("ConsoleApplication1.MyClass1"), IMyClasses)
        ' compiler doesn't know, mc2 is an object
        Dim mc2 = getInstanceFromTypeName("ConsoleApplication1.MyClass2")
        mc1.Foo()
        mc2.foo()
    End Sub
    Private Function getInstanceFromTypeName(typeName As String) As Object
        Dim o As Object
        Try
            o = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(typeName)
        Catch ex As Exception
            o = Nothing
        End Try
        Return o
    End Function
End Module

Public Class MyClass1
    Implements IMyClasses
    Public Sub Foo() Implements IMyClasses.Foo
        Debug.Print("MyClass1")
    End Sub
End Class

Public Class MyClass2
    Implements IMyClasses
    Public Sub Foo() Implements IMyClasses.Foo
        Debug.Print("MyClass2")
    End Sub
End Class

Public Interface IMyClasses
    Sub Foo()
End Interface

mc1.Foo() works because mc1 is declared as an IMyClasses, and IMyClasses defines this subroutine. The compiler knows that IMyClasses defines Foo.

mc2.foo() doesn't work with Option Strict On because Foo() is not a member of Object. With O.S.On, the compiler must be able to resolve all function calls at compile time. It works with Option Strict Off however, as O.S.Off allows function calls on Object, but can potentially be dangerous because O.S.Off also allows mc2.asdf(), for example.

Other resources:

Using System.Reflection

Using System.Activator

Community
  • 1
  • 1
djv
  • 15,168
  • 7
  • 48
  • 72
  • Excellent! Thanks! But, when I'm trying to call my public method I'm getting "Option Strict On Disallows Late Binding". Any way around this? Essentially I have 10 classes all with the same method names. The db drives which class is instantiated and utilized. Thanks. – WebDevGuy Oct 27 '14 at 21:33
  • If you must use option strict, you need to cast your object to the right type. I understand casting to the right type defeats the purpose of loading from a string. This is why you should have an interface that these classes implement which defines the functions / properties you need to access. – djv Oct 27 '14 at 21:40
  • Thanks! Do you have any examples on how to do this? I appreciate it. @Verdolino – WebDevGuy Oct 28 '14 at 02:14
  • @WebDevGuy See the latest edit with an interface implementation. – djv Oct 28 '14 at 14:18