• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 279
  • Last Modified:

Best way to declare and manage a variable that might of differing types?

Here is the situation - I have a base class, from which four other classes are derived. The base class is MustInherit. This base class has four properties that each of the four inherited classes will also have (in addition to other properties). i.e.:
BaseClass (PropertyA, PropertyB, PropertyC, PropertyD)

ClassA (PropertyA, PropertyB, PropertyC, PropertyD)
ClassB (PropertyA, PropertyB, PropertyC, PropertyD)
ClassC (PropertyA, PropertyB, PropertyC, PropertyD)
ClassD (PropertyA, PropertyB, PropertyC, PropertyD)

Now, I have some info in a database. This DB has five fields, which correspond to each of the four property types, and then a fifth field, which says which type of Class it belongs to.

Now in my code, I need to figure out what kind of class to declare, and then apply the properties to that class. Since I don't know ahead of time what kind of class this will be, I'm stuck declaring a new class and all the properties each time. For example:

Select Case ClassType
Case "A"
Dim obj As ClassA
obj.PropertyA = somevalue
obj.PropertyB = somevalue
obj.PropertyC = somevalue
obj.PropertyD = somevalue
Case "B"
Dim obj As ClassB
obj.PropertyA = somevalue
obj.PropertyB = somevalue
obj.PropertyC = somevalue
obj.PropertyD = somevalue
...
...
End Select

As you can see, this leads to a TON of repeated code, and if I need to access that object outside of the Select statement, then I have to about the process of figuring out what type of class it is first in a similar fashion.

Is there a way around this? I mean, what I'd really like to do is something like this:

Dim obj as Object
Select Case ClassType
Case "A" : obj = New ClassA
Case "B" : obj = New ClassB
Case "C" : obj = New ClassC
Case "D" : obj = New ClassD
End Select
obj.PropertyA = somevalue
obj.PropertyB = somevalue
obj.PropertyC = somevalue
obj.PropertyD = somevalue

But the compiler doesn't like that. Note that all my projects run with Option Strict/Explicit
0
toddhd
Asked:
toddhd
  • 2
1 Solution
 
gregoryyoungCommented:
public class ObjFactory
    public shared function GetNewObject(ClassType as String) as BaseClass
          dim obj as BaseClass
          Select Case ClassType
               Case "A" : obj = New ClassA
               Case "B" : obj = New ClassB
               Case "C" : obj = New ClassC
               Case "D" : obj = New ClassD
          End Select
          return obj
    end function
end class

dim obj as BaseClass = ObjFactory.GetNewObject(ClassType)
obj.PropertyA = somevalue
obj.PropertyB = somevalue
obj.PropertyC = somevalue
obj.PropertyD = somevalue


note that by using the factory you have allowed the logic for choosing the object to be externalized from your code that needs the object ( I assume there are many places this will be called).

An even BETTER way would be to have the objects themselves define their "ClassType" and then register them with the factory (i.e. it maintains the ClassType string and the associated type yo factory out dynamically using createinstance() at a later point) I am including a full example of this type of factory here ... the nice thing about it is that it can work dynamically with say a plugin type architecture without needing code changed in the factory class.



A basic example (needless to say that you could do a WHOLE lot more using inheritance ...

Public MustInherit Class BaseClass
    Public MustOverride Function foo() As String
End Class

Public Class ClassA
    Inherits BaseClass
    Public Overrides Function foo() As String
        Return "Class A"
    End Function
End Class

Public Class ClassB
    Inherits BaseClass
    Public Overrides Function foo() As String
        Return "Class B"
    End Function
End Class

Public Class BaseClassFactory
    Private Shared m_Hash As Hashtable = New Hashtable
    Public Shared Sub RegisterClass(ByVal Identifier As String, ByVal Type As Type)
        If Not m_Hash.Contains(Identifier) Then
            m_Hash.Add(Identifier, Type)
        Else
            'let it go or throw an exception
        End If
    End Sub
    Public Shared Function GetObject(ByVal Identifier) As BaseClass
        If m_Hash.Contains(Identifier) Then
            Return Activator.CreateInstance(m_Hash(Identifier))
        Else
            Throw New System.Exception("Unknown identifier : " + Identifier)
        End If
    End Function
End Class

Module Module1

    Sub Main()
        BaseClassFactory.RegisterClass("A", GetType(ClassA))
        BaseClassFactory.RegisterClass("B", GetType(ClassB))

        Dim obj As BaseClass
        Dim data() As String = {"A", "B", "A", "B", "A", "B"}
        For Each element As String In data
            obj = BaseClassFactory.GetObject(element)
            Console.WriteLine(obj.foo())
        Next
    End Sub

End Module


Where this pattern becomes extremely usefull is when you have say a framework assembly that does something ...  by allowing your factory to allow registration you can have your code in this framework use classes provided from outside the framework by an end developer without any prior knowledge of them.

Cheers,

Greg
0
 
toddhdAuthor Commented:
So that's what an object factory is... pretty cool. I've heard the term, but never investigated it. I'll have to dig through the code you posted, but yeah, that sounds like what I'm looking for. Cool paradigm. God I love programming...

Thanks!
0
 
gregoryyoungCommented:
Design Patterns aka GoF (worth buying).
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now