Instantiating objects and storing them at runtime.

jwcoleman87

Well-known member
Joined
Oct 4, 2014
Messages
124
Programming Experience
Beginner
Lets say I have a bunch of objects of type ActionTab (which is an abstract derivation of TabPage)

I've set up a CommentTab, FailureFixTab, and ScreeningTab.

All of these are derived from Action Tab and can be instantiated.

I have a table, looks something like this:
Capture.JPG

This table has fields which will lay out what actions are available in what processes. The application will first query the database to determine the processID of a particular repair, it will then need to query this table and determine what actions are available in that particular process. This part is not difficult and not really what I am concerned about.

The thing I've never done before is somehow connect the integer held in the database (the ActionID)) with the actual object in the application. The objects look like this:

Public MustInherit Class ActionTab : Inherits TabPage


    Private ChildContainer As FlowLayoutPanel
    Private EventHandlerArray As Array
    Public ParentFormReference As Object




    Public Property ChildContainerControl() As FlowLayoutPanel
        Get
            Return ChildContainer
        End Get
        Set(ByVal value As FlowLayoutPanel)
            ChildContainer = value
        End Set
    End Property


    Public Property ControlEventHandlersArray() As Array
        Get
            Return EventHandlerArray
        End Get
        Set(ByVal value As Array)
            EventHandlerArray = value
        End Set
    End Property




    Public Sub New(Name As String, ByRef ParentForm As Object)
        ParentFormReference = ParentForm
        Dim flp As New FlowLayoutPanel
        ChildContainerControl = flp
        flp.FlowDirection = FlowDirection.TopDown
        ChildContainerControl.Parent = Me
        ChildContainerControl.Dock = DockStyle.Fill
        ChildContainerControl.Name = Name
        InitializeControls()
        InitializeEventHandlers()


    End Sub


    Protected MustOverride Sub InitializeControls()
    Protected MustOverride Sub InitializeEventHandlers()
    Protected MustOverride Sub ActionEvent(sender As Object, e As EventArgs)


End Class




It's basically just an abstraction of a tab page with some added event handlers and control initialization functions to make it easier to define tabpages which are useful for the client.

My question is simple: What are my options for connecting the information held in the database (an integer or string) with this class. I want to avoid instantiating all of them but only using a few of them so my goal is to create them on the fly based off of what is laid out in the database. (If this process ID then these actions are available). At that point I want to be able to instantiate them by actionID (or by ActionName)

I haven't googled yet, but that's what I'll be doing throughout the day, I just like to post my questions here first to see if you guys can point me in the right direction.

To clarify the question one more time: Is it possible to associate an integer or string with an object and tell my program what it should do if it is presented with a sequence of ActionID's {0, 1, 2}

Like for each action in ActionID's instantiate the object with actionID of action

I'm thinking maybe an enumeration?
Some kind of array?

On to google!

I'll get back to you guys.
 
I'm checking out Assembly.Load and Activate.CreateInstance() methods, I'm thinking this will lead me in the right direction because apparently you can create instances by using a "fully qualified class name"
 
Alrighty, making my first attempt at this, which doesn't work, can someone explain to me what I'm missing?

        Dim fullyqualifiedclassname As String = "Teletrack.CommentTab"
        Dim o = fetchInstance(fullyqualifiedclassname)

    Private Function fetchInstance(ByVal fullyQualifiedClassName As String) As Object
        Dim o As Object = Nothing
        Try
            o = Assembly.Load("Teletrack").CreateInstance(fullyQualifiedClassName)
        Catch ex As Exception
        End Try


        Return o
    End Function



This code throws an exception: Constructor on type 'Teletrack.CommentTab' not found.

I've been reading around and it's saying that "there is no public constructor available" according to the msdn

Well here is my code for the actual class I'm trying to instantiate:

    Public Class CommentTab : Inherits ActionTab


        Public Sub New(ByRef ParentForm As Object)
            MyBase.New("Comments", ParentForm)
        End Sub
        Protected Overrides Sub InitializeControls()
            Try
                Dim lblComments As New Label With {.Parent = Me.ChildContainerControl, .Text = "Comments:"}
                Dim txtComments As New TextBox With {.Parent = Me.ChildContainerControl, .Name = "CommentBox", .Width = 250, .Height = 100, .Multiline = True}
                Dim btnSaveComment As New Button With {.Parent = Me.ChildContainerControl, .Name = "btnSaveComment", .Text = "Save"}
            Catch ex As Exception


            End Try


        End Sub
        Protected Overrides Sub InitializeEventHandlers()
            Try
                AddHandler ChildContainerControl.Controls.Find("btnSaveComment", True)(0).Click, AddressOf Me.ActionEvent
            Catch ex As Exception


            End Try


        End Sub
        Protected Overrides Sub ActionEvent(sender As Object, e As EventArgs)
            Dim rc As New RepairControl
            If IsNothing(ParentFormReference.RepairInformation) Then
                MsgBox("RepairInformation is empty!")
            Else
                rc.SetStatusAndAssignment(ParentFormReference.RepairInformation.SerialNumber, ParentFormReference.User,
                                          ParentFormReference.RepairInformation.Status, ChildContainerControl.Controls.Find("CommentBox", True)(0).Text)
            End If
        End Sub
    End Class




Anyone know how to fix this?
 
Okay, so I got this thing to work, with a few modifications:

Capture.JPG

First I had to change the constructor to have no parameters, and then supply ways to set up a data reference within the class:

Public MustInherit Class ActionTab : Inherits TabPage


    Private ChildContainer As FlowLayoutPanel
    Private EventHandlerArray As Array
    Public ParentFormReference As Object


    Public Property ChildContainerControl() As FlowLayoutPanel
        Get
            Return ChildContainer
        End Get
        Set(ByVal value As FlowLayoutPanel)
            ChildContainer = value
        End Set
    End Property


    Public Property ControlEventHandlersArray() As Array
        Get
            Return EventHandlerArray
        End Get
        Set(ByVal value As Array)
            EventHandlerArray = value
        End Set
    End Property


    Public Sub New()
        Dim flp As New FlowLayoutPanel
        ChildContainerControl = flp
        flp.FlowDirection = FlowDirection.TopDown
        ChildContainerControl.Parent = Me
        ChildContainerControl.Dock = DockStyle.Fill
        ChildContainerControl.Name = Name
        InitializeControls()
        InitializeEventHandlers()
    End Sub
    Public Sub New(Name As String, ByRef ParentForm As Object)
        ParentFormReference = ParentForm
        Dim flp As New FlowLayoutPanel
        ChildContainerControl = flp
        flp.FlowDirection = FlowDirection.TopDown
        ChildContainerControl.Parent = Me
        ChildContainerControl.Dock = DockStyle.Fill
        ChildContainerControl.Name = Name
        InitializeControls()
        InitializeEventHandlers()


    End Sub


    Public Sub SetDataReference(ByRef DataRef As Object)
        ParentFormReference = DataRef
    End Sub


    Protected MustOverride Sub InitializeControls()
    Protected MustOverride Sub InitializeEventHandlers()
    Protected MustOverride Sub ActionEvent(sender As Object, e As EventArgs)


End Class




Once this was completed I was able to use this code to instantiate the object and get it initialized:

    Private Function fetchInstance(ByVal fullyQualifiedClassName As String) As Object
        Dim o As Object = Nothing
        Try
            o = Assembly.Load("Teletrack").CreateInstance(fullyQualifiedClassName)
            TabControl1.TabPages.Add(o)
            DirectCast(o, ActionTab).Text = "Add Comments"
            DirectCast(o, ActionTab).SetDataReference(Me)


        Catch ex As Exception
            MsgBox(ex.Message)
        End Try




        Return o
    End Function


That code created the tab page you saw in my first image, complete with event handlers!

The final step now is to set up the database so that it knows the fullyqualifiedclassname and the header text for the tabs, and finally this will all become automated!
 
Last edited:
And here we have it, dynamic tab pages designed to allow a technician to interact with a database record of a specific unit. All initialized and created on the fly as defined by the database:

    Private Sub DisplayAvailableActions()
        Dim rc As New RepairControl
        Dim o As Object = Nothing
        For Each processaction In rc.GetAvailableActions(rc.GetProcessID(Department, RepairInformation.Status), Department)
            Try
                o = Assembly.Load("Teletrack").CreateInstance(processaction.ClassName)
                TabControl1.TabPages.Add(o)
                DirectCast(o, ActionTab).Text = processaction.Title
                DirectCast(o, ActionTab).SetDataReference(Me)


            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        Next




    End Sub


    Public Function GetAvailableActions(ProcessID As Integer, DepartmentID As Integer) As Array
        Using db As New ProductionDataModelDataContext
            Dim AvailableActions = From ta In db.TTActions _
                                   Join tpa In db.TTProcessActions On ta.ActionID Equals tpa.ActionID _
                                   Where tpa.ProcessID = ProcessID _
                                   And tpa.DepartmentID = DepartmentID _
                                   Select ta.ClassName, ta.Title


            Return AvailableActions.ToArray


        End Using
    End Function
 
Back
Top