Home All Groups Group Topic Archive Search About

Design Question for Factory Pattern and Casting Types

Author
13 May 2006 1:45 AM
GarrettD78
Accidently posted this to the wrong group so I am reposting.
This is probably a newbie question but I am a little confused about how to go
next with my code. I think I want to use a factory pattern in this situation
but I am having trouble getting access to properties at the presentation
level. So my situation is I have a Vehicle base class.

Public Class Vehicle
  Property BodyType as String
End Class

Then I have multiple inherited Classes
Public Class Truck inherits Vehicle
  Property Weight as String
End Class

Public Class Forklift inherits Vehicle
  Property EngineType as String
End Class

My factory uses a select statement on the Body Type to decide which class to
instantiate.
Public Class VehicleFactory
   Public Shared Function CreateVehicleInstance(bodyType as String) as Vehicle
     Select Case bodyType
                   Case "Truck"
                        return v as New Truck
                    Case "Forklift"
                        return v as New Forklift
    End Select
         return v
    End Function
End Class

My problems comes when I try return my class from the factory and access
properties of the inherited class. The compiler won't let me compile it and I
am not sure where to go. So for exampl

Dim v as Vehicle = VehicleFactory.CreateVehicleInstance("Truck")

v.Weight = 6 'this give me a compile error that Weight is not a member of 
the base class

I am trying to use this on the form and once the object is created then I
need it accesible to the form to track whether it needs to be saved back to
the database or not. Am I going about this all wrong?

Author
13 May 2006 4:20 PM
jayeldee
You probably want to change..
Dim v as Vehicle = VehicleFactory.CreateVehicleInstance("Truck")
to
Dim t as Truck = VehicleFactory.CreateVehicleInstance("Truck")
so you can access the Truck variables.
Author
13 May 2006 10:19 PM
GarrettD78
Right I understand that I would rather cast to the Truck, but the problem is
that the type of object is specified at runtime. I want to create an object
on my main form that all my child forms have access to. But I don't know
which sub class of my family of vehicles the user will choose at runtime.
That's why I thought about using the Ctype function, but then I don't have
access to properties in the subclass and I get a compile error.

Show quoteHide quote
"jayeldee" wrote:

> You probably want to change..
> Dim v as Vehicle = VehicleFactory.CreateVehicleInstance("Truck")
> to
> Dim t as Truck = VehicleFactory.CreateVehicleInstance("Truck")
> so you can access the Truck variables.
>
>
Author
14 May 2006 3:36 PM
rmacias
Can't you try something like:

If TypeOf (v) Is Truck Then
            CType(v, Truck).Weight = "6"
End If

Show quoteHide quote
"GarrettD78" wrote:

> Accidently posted this to the wrong group so I am reposting.
> This is probably a newbie question but I am a little confused about how to go
> next with my code. I think I want to use a factory pattern in this situation
> but I am having trouble getting access to properties at the presentation
> level. So my situation is I have a Vehicle base class.
>
> Public Class Vehicle
>   Property BodyType as String
> End Class
>
> Then I have multiple inherited Classes
> Public Class Truck inherits Vehicle
>   Property Weight as String
> End Class
>
> Public Class Forklift inherits Vehicle
>   Property EngineType as String
> End Class
>
> My factory uses a select statement on the Body Type to decide which class to
> instantiate.
> Public Class VehicleFactory
>    Public Shared Function CreateVehicleInstance(bodyType as String) as Vehicle
>      Select Case bodyType
>                    Case "Truck"
>                         return v as New Truck
>                     Case "Forklift"
>                         return v as New Forklift
>     End Select
>          return v
>     End Function
> End Class
>
> My problems comes when I try return my class from the factory and access
> properties of the inherited class. The compiler won't let me compile it and I
> am not sure where to go. So for exampl
>
> Dim v as Vehicle = VehicleFactory.CreateVehicleInstance("Truck")
>
> v.Weight = 6 'this give me a compile error that Weight is not a member of 
> the base class
>
> I am trying to use this on the form and once the object is created then I
> need it accesible to the form to track whether it needs to be saved back to
> the database or not. Am I going about this all wrong?
>
>
>

>
Author
15 May 2006 2:42 AM
GarrettD78
I was hoping that someone might know how to to cast the type so I would have
to do a switch statement everytime I had to deal with this object. I want to
have a variable that is part of my form, that way once it is instantiated
then I don't have to worry about the types. This is a big problem because the
Truck is not the only vehicle that I will be dealing with. I think I am going
about this wrong, but I can't figure out the right way to do it.

I have a main form that they will enter the the vehicle information and then
there will be other forms that build off the main one. I guess maybe how
could I create an object when the user clicks the "Save" button and not let
it get out of scope while the form is open. The only way I know to do this is
to create a Private variable, but you have to give it a type and then I can
instantiate it, but when the form loads I don't know the type. I guess I need
to re-think this.

Show quoteHide quote
"rmacias" wrote:

> Can't you try something like:
>
> If TypeOf (v) Is Truck Then
>             CType(v, Truck).Weight = "6"
> End If
>
> "GarrettD78" wrote:
>
> > Accidently posted this to the wrong group so I am reposting.
> > This is probably a newbie question but I am a little confused about how to go
> > next with my code. I think I want to use a factory pattern in this situation
> > but I am having trouble getting access to properties at the presentation
> > level. So my situation is I have a Vehicle base class.
> >
> > Public Class Vehicle
> >   Property BodyType as String
> > End Class
> >
> > Then I have multiple inherited Classes
> > Public Class Truck inherits Vehicle
> >   Property Weight as String
> > End Class
> >
> > Public Class Forklift inherits Vehicle
> >   Property EngineType as String
> > End Class
> >
> > My factory uses a select statement on the Body Type to decide which class to
> > instantiate.
> > Public Class VehicleFactory
> >    Public Shared Function CreateVehicleInstance(bodyType as String) as Vehicle
> >      Select Case bodyType
> >                    Case "Truck"
> >                         return v as New Truck
> >                     Case "Forklift"
> >                         return v as New Forklift
> >     End Select
> >          return v
> >     End Function
> > End Class
> >
> > My problems comes when I try return my class from the factory and access
> > properties of the inherited class. The compiler won't let me compile it and I
> > am not sure where to go. So for exampl
> >
> > Dim v as Vehicle = VehicleFactory.CreateVehicleInstance("Truck")
> >
> > v.Weight = 6 'this give me a compile error that Weight is not a member of 
> > the base class
> >
> > I am trying to use this on the form and once the object is created then I
> > need it accesible to the form to track whether it needs to be saved back to
> > the database or not. Am I going about this all wrong?
> >
> >
> >
> > 
> >
Author
15 May 2006 3:39 AM
rmacias
You can try something like this.  You can create a series of interfaces and
abstract classes for your vehicles.  You can also then create an "instance"
class that will hold your current instance of any vehicle created from the
factory.  From there, you can pass it around to anyform you wish, and not
have to worry about the type it is.

The Below code is not throughly tested and is propably not the most ideal
design, but it does get the point across and can perhaps serve as a starting
point for you.  Modify it as you see fit:

Public Interface IVehicle

    ReadOnly Property BodyType() As String

End Interface

Public Interface ITruck

    Property Weight() As String

End Interface

Public Interface IForklift

    Property EngineType() As String

End Interface

Public MustInherit Class Vehicle
    Implements IVehicle

    Protected bodyT As String

    Public Sub New()

    End Sub

    Public Sub New(ByVal bdyTp As String)
        Me.bodyT = bdyTp
    End Sub

    Public ReadOnly Property BodyType() As String Implements IVehicle.BodyType
        Get
            Return Me.bodyT
        End Get
    End Property

End Class

Public Class Truck
    Inherits Vehicle
    Implements ITruck

    Private wt As String


    Public Sub New(ByVal bdyTp As String)
        Me.bodyT = bdyTp
    End Sub

    Public Property Weight() As String Implements ITruck.Weight
        Get
            Return Me.wt
        End Get
        Set(ByVal Value As String)
            'Validate that Value is a valid weight, if it is assign it
            Me.wt = Value
        End Set
    End Property

End Class

Public Class Forklift
    Inherits Vehicle
    Implements IForklift

    Private engineT As String

    Public Sub New(ByVal bdyTp As String)
        Me.bodyT = bdyTp
    End Sub

    Public Property EngineType() As String Implements IForklift.EngineType
        Get
            Return Me.engineT
        End Get
        Set(ByVal Value As String)
            'Validate that Value is a valid EngineType
            Me.engineT = Value
        End Set
    End Property

End Class

Public Class VehicleFactory

    Public Shared Function CreateVehicle(ByVal bdyTyp As String) As Vehicle

        Dim asm As [Assembly]
        Dim asmTypes() As Type

        'Create an instance of the executing assembly
        asm = [Assembly].GetExecutingAssembly()

        'Get a list of types from the current executing assembly
        asmTypes = asm.GetTypes()

        Dim typeNamespace As String
        Dim typeToLookFor As String

        For Each currentType As Type In asmTypes

            'Derive the namespace of the current type of the list
            typeNamespace = currentType.Namespace

            'Derive the fully qualified name of the type we are looking for
            typeToLookFor = typeNamespace & "." & bdyTyp

            'If the current type matches the type we are looking for, return
an instance of it.
            'The comparison is case sensitive
            If String.Compare(typeToLookFor, currentType.FullName, False) =
0 Then
                'Create the parameters for the constructor
                Dim args() As Object = {bdyTyp}
                Return Activator.CreateInstance(currentType, args)
            End If

        Next

        'If we get this far, the type we were looking was not found in the
assembly
        Throw New Exception("The type " & bdyTyp & " was not found in the
assembly.")

    End Function

End Class

Public Class VehicleInstance
    Implements IVehicle, ITruck, IForklift

    Private m_currentVehicle As Vehicle

    Public Sub New(ByVal bdyT As String)

        Me.m_currentVehicle = VehicleFactory.CreateVehicle(bdyT)

    End Sub

    Public Property EngineType() As String Implements IForklift.EngineType
        Get
            If TypeOf (Me.m_currentVehicle) Is Forklift Then
                Return CType(Me.m_currentVehicle, Forklift).EngineType
            Else
                'Either return Nothing, Empty String, Or Throw Exception
            End If
        End Get
        Set(ByVal Value As String)

            If TypeOf (Me.m_currentVehicle) Is Forklift Then
                CType(Me.m_currentVehicle, Forklift).EngineType = Value
            Else
                'Throw exception or something else
            End If

        End Set
    End Property

    Public Property Weight() As String Implements ITruck.Weight
        Get
            If TypeOf (Me.m_currentVehicle) Is Truck Then
                Return CType(Me.m_currentVehicle, Truck).Weight
            Else
                'Either return Nothing, Empty String, Or Throw Exception
            End If
        End Get
        Set(ByVal Value As String)
            If TypeOf (Me.m_currentVehicle) Is Truck Then
                CType(Me.m_currentVehicle, Truck).Weight = Value
            Else
                'Throw exception or something else
            End If
        End Set
    End Property

    Public ReadOnly Property BodyType() As String Implements IVehicle.BodyType
        Get
            Return Me.m_currentVehicle.BodyType
        End Get
    End Property
End Class

Sub Main()

        Dim v As New VehicleInstance("Truck")

        v.Weight = 6

End Sub

Show quoteHide quote
"GarrettD78" wrote:

> I was hoping that someone might know how to to cast the type so I would have
> to do a switch statement everytime I had to deal with this object. I want to
> have a variable that is part of my form, that way once it is instantiated
> then I don't have to worry about the types. This is a big problem because the
> Truck is not the only vehicle that I will be dealing with. I think I am going
> about this wrong, but I can't figure out the right way to do it.
>
> I have a main form that they will enter the the vehicle information and then
> there will be other forms that build off the main one. I guess maybe how
> could I create an object when the user clicks the "Save" button and not let
> it get out of scope while the form is open. The only way I know to do this is
> to create a Private variable, but you have to give it a type and then I can
> instantiate it, but when the form loads I don't know the type. I guess I need
> to re-think this.
>
> "rmacias" wrote:
>
> > Can't you try something like:
> >
> > If TypeOf (v) Is Truck Then
> >             CType(v, Truck).Weight = "6"
> > End If
> >
> > "GarrettD78" wrote:
> >
> > > Accidently posted this to the wrong group so I am reposting.
> > > This is probably a newbie question but I am a little confused about how to go
> > > next with my code. I think I want to use a factory pattern in this situation
> > > but I am having trouble getting access to properties at the presentation
> > > level. So my situation is I have a Vehicle base class.
> > >
> > > Public Class Vehicle
> > >   Property BodyType as String
> > > End Class
> > >
> > > Then I have multiple inherited Classes
> > > Public Class Truck inherits Vehicle
> > >   Property Weight as String
> > > End Class
> > >
> > > Public Class Forklift inherits Vehicle
> > >   Property EngineType as String
> > > End Class
> > >
> > > My factory uses a select statement on the Body Type to decide which class to
> > > instantiate.
> > > Public Class VehicleFactory
> > >    Public Shared Function CreateVehicleInstance(bodyType as String) as Vehicle
> > >      Select Case bodyType
> > >                    Case "Truck"
> > >                         return v as New Truck
> > >                     Case "Forklift"
> > >                         return v as New Forklift
> > >     End Select
> > >          return v
> > >     End Function
> > > End Class
> > >
> > > My problems comes when I try return my class from the factory and access
> > > properties of the inherited class. The compiler won't let me compile it and I
> > > am not sure where to go. So for exampl
> > >
> > > Dim v as Vehicle = VehicleFactory.CreateVehicleInstance("Truck")
> > >
> > > v.Weight = 6 'this give me a compile error that Weight is not a member of 
> > > the base class
> > >
> > > I am trying to use this on the form and once the object is created then I
> > > need it accesible to the form to track whether it needs to be saved back to
> > > the database or not. Am I going about this all wrong?
> > >
> > >
> > >
> > > 
> > >
Author
15 May 2006 1:52 PM
GarrettD78
That looks pretty cool. I will try this thanks.

Show quoteHide quote
"rmacias" wrote:

> You can try something like this.  You can create a series of interfaces and
> abstract classes for your vehicles.  You can also then create an "instance"
> class that will hold your current instance of any vehicle created from the
> factory.  From there, you can pass it around to anyform you wish, and not
> have to worry about the type it is.
>
> The Below code is not throughly tested and is propably not the most ideal
> design, but it does get the point across and can perhaps serve as a starting
> point for you.  Modify it as you see fit:
>
> Public Interface IVehicle
>
>     ReadOnly Property BodyType() As String
>
> End Interface
>
> Public Interface ITruck
>
>     Property Weight() As String
>
> End Interface
>
> Public Interface IForklift
>
>     Property EngineType() As String
>
> End Interface
>
> Public MustInherit Class Vehicle
>     Implements IVehicle
>
>     Protected bodyT As String
>
>     Public Sub New()
>
>     End Sub
>
>     Public Sub New(ByVal bdyTp As String)
>         Me.bodyT = bdyTp
>     End Sub
>
>     Public ReadOnly Property BodyType() As String Implements IVehicle.BodyType
>         Get
>             Return Me.bodyT
>         End Get
>     End Property
>
> End Class
>
> Public Class Truck
>     Inherits Vehicle
>     Implements ITruck
>
>     Private wt As String
>
>
>     Public Sub New(ByVal bdyTp As String)
>         Me.bodyT = bdyTp
>     End Sub
>
>     Public Property Weight() As String Implements ITruck.Weight
>         Get
>             Return Me.wt
>         End Get
>         Set(ByVal Value As String)
>             'Validate that Value is a valid weight, if it is assign it
>             Me.wt = Value
>         End Set
>     End Property
>
> End Class
>
> Public Class Forklift
>     Inherits Vehicle
>     Implements IForklift
>
>     Private engineT As String
>
>     Public Sub New(ByVal bdyTp As String)
>         Me.bodyT = bdyTp
>     End Sub
>
>     Public Property EngineType() As String Implements IForklift.EngineType
>         Get
>             Return Me.engineT
>         End Get
>         Set(ByVal Value As String)
>             'Validate that Value is a valid EngineType
>             Me.engineT = Value
>         End Set
>     End Property
>
> End Class
>
> Public Class VehicleFactory
>
>     Public Shared Function CreateVehicle(ByVal bdyTyp As String) As Vehicle
>
>         Dim asm As [Assembly]
>         Dim asmTypes() As Type
>
>         'Create an instance of the executing assembly
>         asm = [Assembly].GetExecutingAssembly()
>
>         'Get a list of types from the current executing assembly
>         asmTypes = asm.GetTypes()
>
>         Dim typeNamespace As String
>         Dim typeToLookFor As String
>
>         For Each currentType As Type In asmTypes
>
>             'Derive the namespace of the current type of the list
>             typeNamespace = currentType.Namespace
>
>             'Derive the fully qualified name of the type we are looking for
>             typeToLookFor = typeNamespace & "." & bdyTyp
>
>             'If the current type matches the type we are looking for, return
> an instance of it.
>             'The comparison is case sensitive
>             If String.Compare(typeToLookFor, currentType.FullName, False) =
> 0 Then
>                 'Create the parameters for the constructor
>                 Dim args() As Object = {bdyTyp}
>                 Return Activator.CreateInstance(currentType, args)
>             End If
>
>         Next
>
>         'If we get this far, the type we were looking was not found in the
> assembly
>         Throw New Exception("The type " & bdyTyp & " was not found in the
> assembly.")
>
>     End Function
>
> End Class
>
> Public Class VehicleInstance
>     Implements IVehicle, ITruck, IForklift
>
>     Private m_currentVehicle As Vehicle
>
>     Public Sub New(ByVal bdyT As String)
>
>         Me.m_currentVehicle = VehicleFactory.CreateVehicle(bdyT)
>
>     End Sub
>
>     Public Property EngineType() As String Implements IForklift.EngineType
>         Get
>             If TypeOf (Me.m_currentVehicle) Is Forklift Then
>                 Return CType(Me.m_currentVehicle, Forklift).EngineType
>             Else
>                 'Either return Nothing, Empty String, Or Throw Exception
>             End If
>         End Get
>         Set(ByVal Value As String)
>
>             If TypeOf (Me.m_currentVehicle) Is Forklift Then
>                 CType(Me.m_currentVehicle, Forklift).EngineType = Value
>             Else
>                 'Throw exception or something else
>             End If
>
>         End Set
>     End Property
>
>     Public Property Weight() As String Implements ITruck.Weight
>         Get
>             If TypeOf (Me.m_currentVehicle) Is Truck Then
>                 Return CType(Me.m_currentVehicle, Truck).Weight
>             Else
>                 'Either return Nothing, Empty String, Or Throw Exception
>             End If
>         End Get
>         Set(ByVal Value As String)
>             If TypeOf (Me.m_currentVehicle) Is Truck Then
>                 CType(Me.m_currentVehicle, Truck).Weight = Value
>             Else
>                 'Throw exception or something else
>             End If
>         End Set
>     End Property
>
>     Public ReadOnly Property BodyType() As String Implements IVehicle.BodyType
>         Get
>             Return Me.m_currentVehicle.BodyType
>         End Get
>     End Property
> End Class
>
>  Sub Main()
>
>         Dim v As New VehicleInstance("Truck")
>
>         v.Weight = 6
>
>  End Sub
>
> "GarrettD78" wrote:
>
> > I was hoping that someone might know how to to cast the type so I would have
> > to do a switch statement everytime I had to deal with this object. I want to
> > have a variable that is part of my form, that way once it is instantiated
> > then I don't have to worry about the types. This is a big problem because the
> > Truck is not the only vehicle that I will be dealing with. I think I am going
> > about this wrong, but I can't figure out the right way to do it.
> >
> > I have a main form that they will enter the the vehicle information and then
> > there will be other forms that build off the main one. I guess maybe how
> > could I create an object when the user clicks the "Save" button and not let
> > it get out of scope while the form is open. The only way I know to do this is
> > to create a Private variable, but you have to give it a type and then I can
> > instantiate it, but when the form loads I don't know the type. I guess I need
> > to re-think this.
> >
> > "rmacias" wrote:
> >
> > > Can't you try something like:
> > >
> > > If TypeOf (v) Is Truck Then
> > >             CType(v, Truck).Weight = "6"
> > > End If
> > >
> > > "GarrettD78" wrote:
> > >
> > > > Accidently posted this to the wrong group so I am reposting.
> > > > This is probably a newbie question but I am a little confused about how to go
> > > > next with my code. I think I want to use a factory pattern in this situation
> > > > but I am having trouble getting access to properties at the presentation
> > > > level. So my situation is I have a Vehicle base class.
> > > >
> > > > Public Class Vehicle
> > > >   Property BodyType as String
> > > > End Class
> > > >
> > > > Then I have multiple inherited Classes
> > > > Public Class Truck inherits Vehicle
> > > >   Property Weight as String
> > > > End Class
> > > >
> > > > Public Class Forklift inherits Vehicle
> > > >   Property EngineType as String
> > > > End Class
> > > >
> > > > My factory uses a select statement on the Body Type to decide which class to
> > > > instantiate.
> > > > Public Class VehicleFactory
> > > >    Public Shared Function CreateVehicleInstance(bodyType as String) as Vehicle
> > > >      Select Case bodyType
> > > >                    Case "Truck"
> > > >                         return v as New Truck
> > > >                     Case "Forklift"
> > > >                         return v as New Forklift
> > > >     End Select
> > > >          return v
> > > >     End Function
> > > > End Class
> > > >
> > > > My problems comes when I try return my class from the factory and access
> > > > properties of the inherited class. The compiler won't let me compile it and I
> > > > am not sure where to go. So for exampl
> > > >
> > > > Dim v as Vehicle = VehicleFactory.CreateVehicleInstance("Truck")
> > > >
> > > > v.Weight = 6 'this give me a compile error that Weight is not a member of 
> > > > the base class
> > > >
> > > > I am trying to use this on the form and once the object is created then I
> > > > need it accesible to the form to track whether it needs to be saved back to
> > > > the database or not. Am I going about this all wrong?
> > > >
> > > >
> > > >
> > > > 
> > > >