|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Design Question for Factory Pattern and Casting TypesThis 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? 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. 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. > > 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? > > > > > 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? > > > > > > > > > > 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? > > > > > > > > > > > > > > > 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? > > > > > > > > > > > > > > > > > > > > |
|||||||||||||||||||||||