I suppose to use T but i am not sure how do it in proper way.
Let's consider following example.
Base class:
Public Class HtmlBase
Implements IGetInformation
Public Overridable Function IsExist() As Boolean Implements IGetInformation.IsExist
Throw New NotImplementedException()
End Function
Public Overridable Function GetIdByName(pName As String) As Integer Implements IGetInformation.GetIdByName
Throw New NotImplementedException()
End Function
End Class
Example classes which inherit from base class:
Public Class HtmlSubSection
Inherits HtmlBase
'--sometimes i have to overload to add additioinal parameter
Public Overloads Function isExist(subsection As String) As Boolean
Dim dlsubkategorie As New DataLayer.DALSubSection
Return dlsubkategorie.CheckIfSubSectionExist(subsection)
End Function
Public Overrides Function GetIdByName(subsectionName As String) As Integer
Dim dlget As New DataLayer.DALSubSection
Return dlget.GetSubSectionIdByName(subsectionName)
End Function
End Class
Public Class HtmlSection
Inherits HtmlBase
'sometime i have to overload to add additioinal parameter
Public Overloads Function IsExist(section As String) As Boolean
Dim dlsubkategorie As New DataLayer.DALSection
Return dlsubkategorie.CheckIfSectionExist(section)
End Function
Public Overrides Function GetIdByName(Name As String) As Integer
Dim dlsubkategorie As New DataLayer.DALSection
Return dlsubkategorie.GetSectionIdByName(Name)
End Function
End Class
As could be seen above two classes which inherits from base within their methods has same logic (sometimes i have to use additional parameter therefore overloads there, but are using diffrent DAL class to call. I would like to implement this logic in base class and for each just point to specific DAL. How to do that to not everytime in those classes write e.g:
Dim dlsubkategorie As New DataLayer.<DALSection>
Return dlsubkategorie.GetSectionIdByName(Name)
EDIT:
Htmlbase constructor's:
Sub New()
End Sub
Sub New(pId As Integer)
_Id = pId
End Sub
HtmlSubSection's constructors:
Sub New()
MyBase.New()
AvailableSentences = New List(Of HtmlSubSection_Sentence)
SelectedSentences = New List(Of HtmlSubSection_Sentence)
End Sub
Sub New(pId As Integer)
MyBase.New(pId)
End Sub
Sub New(pName As String)
_Name = pName
End Sub
Sub New(pId As Integer, pName As String)
MyBase.New(pId)
_Name = pName
End Sub
HtmlSection's constructors:
Sub New()
MyBase.New()
End Sub
Sub New(pId As Integer)
MyBase.New(pId)
End Sub
Sub New(pId As Integer, pName As String, pPosition As Integer)
MyBase.New(pId)
_Name = pName
_Position = pPosition
End Sub
Sub New(pName As String)
_Name = pName
End Sub
Sub New(pName As String, pPosition As Integer)
_Name = pName
_Position = pPosition
End Sub
You donĀ“t need generic types here. Just use Interfaces, Sub Classing and Polymorphism correctly.
New Interface IDAL which is implemented by DAL classes to get rid of different method names which take same parameters and do the same:
Public Interface IDAL
Function CheckIfSectionExist(section As string) As Boolean
Function GetSectionIdByName(section As string) As Integer
End Interface
Public Class DALSection
Implements IDAL
Public Function CheckIfSectionExist(section As string) As Boolean Implements IDAL.CheckIfSectionExist
...
End Function
Public Function GetSectionIdByName(section As String) As Integer Implements IDAL.GetSectionIdByName
...
End Function
End Class
Public Class DALSubSection
Implements IDAL
Public Function CheckIfSubSectionExist(subSection As string) As Boolean Implements IDAL.CheckIfSectionExist
...
End Function
Public Function GetSubSectionIdByName(subSection As String) As Integer Implements IDAL.GetSectionIdByName
...
End Function
End Class
Base class changed to abstract and the constructor now takes IDAL parameter. Function can now be executed polymorphic. Added a isExists(string) function to avoid overloading:
Public MustInherit Class HtmlBase
Implements IGetInformation
Public Property DAL as DataLayer.IDAL
Protected Sub New(dal as DataLayer.IDAL)
Me.DAL = dal
End Sub
Public Overridable Function isExist() As Boolean Implements IGetInformation.isExist
Return True
End Function
Public Overridable Function isExist(section As String) As Boolean
Return DAL.CheckIfSectionExist(Section)
End Function
Public Overridable Function GetIdByName(pName As String) As Integer Implements IGetInformation.GetIdByName
Return DAL.GetSectionIdByName(pName)
End Function
End Class
Client classes only need to give correct DAL to base class:
Public Class HtmlSubSection
Inherits HtmlBase
Public Sub New()
MyBase.New(New DataLayer.DALSubSection)
End Sub
End Class
Public Class HtmlSection
Inherits HtmlBase
Public Sub New()
MyBase.New(New DataLayer.DALSection)
End Sub
End Class
Basically it would be ideal if IGetInformation had a isExist method with an optional string parameter. This would save one unneccessary method in HtmlBase.
Related
Imports Kerry_Sales_Project
' base class
Public Class Bonus
Public Property SalesId As String
Public Property Sales As Double
' default constructor
Public Sub New()
_SalesId = String.Empty
_Sales = 0
End Sub
' parameterized constructor
Public Sub New(ByVal strId As String, ByVal dblSold As Double)
SalesId = strId
Sales = dblSold
End Sub
' GetBonus method
Public Overridable Function GetBonus() As Double
Return _Sales * 0.05
End Function
Public Shared Widening Operator CType(v As PremiumBonus) As Bonus
Throw New NotImplementedException()
End Operator
End Class
' derived class
Public Class PremiumBonus
Public Property Sales As Double
Public Property strId As String
' default constructor
Public Sub New(strId As String)
MyBase.New()
End Sub
' parameterized constructor
Public Sub New(ByVal strId As String, ByVal dblSold As Double)
MyBase.New(strId, dblSold)
End Sub
' class method
Public Overrides Function GetBonus() As Double
Return MyBase.GetBonus() + (Sales - 2500) * 0.01
End Function
End Class
In effect, you forgot to place Inherits Bonus in the Premium Bonus class. It would be something like
Public Class PremiumBonus: Inherits Bonus
And the other thing is the CType operator overload.
Public Shared Widening Operator CType(v As PremiumBonus) As Bonus
Throw New NotImplementedException()
End Operator
This operator overload is not necessary because the PremiumBonus class is a child of Bunus and they are contained.
I have custom attribute applied to CRUD repository methods to control access:
Public Class SecureDbContextGenericRepository(Of TEntity As Class, TContext As DbContext)
Inherits DbContextGenericRepository(Of TEntity, TContext)
Public Sub New(connectionService As IConnectionService)
MyBase.New(connectionService)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Delete(ParamArray entities() As TEntity)
MyBase.Delete(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Insert(ParamArray entities() As TEntity)
MyBase.Insert(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataReader)>
Public Overrides Function [Select](Optional predicate As Func(Of TEntity, Boolean) = Nothing) As IList(Of TEntity)
Return MyBase.Select(predicate)
End Function
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Update(ParamArray entities() As TEntity)
MyBase.Update(entities)
End Sub
End Class
This is implementation of attribute:
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Property EmployeeRoles As EmployeeRoles
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
And permission:
Public Class EmployeeRolePermission
Implements IPermission
Public Sub New(employeeRoles As EmployeeRoles)
_EmployeeRoles = employeeRoles
End Sub
Public Function Copy() As IPermission Implements IPermission.Copy
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Sub Demand() Implements IPermission.Demand
Dim principal = DirectCast(Thread.CurrentPrincipal, ProductionAssistantPrincipal)
If Not principal.IsInRole(_EmployeeRoles) Then
Throw New SecurityException(String.Format(My.Resources.EmployeeRoleNotFound,
principal.Identity.Name,
_EmployeeRoles.ToString()))
End If
End Sub
Public Sub FromXml(e As SecurityElement) Implements ISecurityEncodable.FromXml
Throw New NotImplementedException()
End Sub
Public Function Intersect(target As IPermission) As IPermission Implements IPermission.Intersect
Return New EmployeeRolePermission(_EmployeeRoles And DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function IsSubsetOf(target As IPermission) As Boolean Implements IPermission.IsSubsetOf
Return _EmployeeRoles.HasFlag(DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function ToXml() As SecurityElement Implements ISecurityEncodable.ToXml
Throw New NotImplementedException()
End Function
Public Function Union(target As IPermission) As IPermission Implements IPermission.Union
Return New EmployeeRolePermission(_EmployeeRoles Or DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public ReadOnly Property EmployeeRoles As EmployeeRoles
End Class
Every time one of the CRUD methods are reached, TypeLoadException is thrown. I really dont know cause of this, but if I remove attributes from CRUD methods, everything works fine.
This seems to be due to the enum-valued property on the attribute (see https://connect.microsoft.com/VisualStudio/feedback/details/596251/custom-cas-attributes-with-an-enum-property-set-cause-a-typeloadexception for details). To work around this issue, you could use a string-valued property on the attribute and cast to an enum either in the property setter or just before creating the permission. (Personally, I'd probably opt for the former in the interests of enabling early validation, but ymmv...)
Another workaround is making attribute property of type, which is used in Enum, in this case Integer.
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(CType(_RequiredEmployeeRoles, EmployeeRoles))
End Function
Public Property RequiredEmployeeRoles As Integer
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
Then you dont need to use String, which does not allow easy combining of flags when attribute is used:
<EmployeeRoleRequirement(SecurityAction.Demand, RequiredEmployeeRoles:=EmployeeRoles.DataReader Or EmployeeRoles.DataWriter)>
Sub SecuredMethod()
End Sub
I have an abstract class as
Public MustInherit Class GenericClass
Public Sub New(Byval x as Integer)
' Some code here
End Sub
End Class
I inherit this class to another class as follows:
Public Class SpecificClass
Inherits GenericClass
Public Sub New(Byval x as Integer)
MyBase.New(x)
End Sub
End Class
I want to add a Shared Function e.g. magicFunction in such a way that when I use it, it should return an object of type SpecificClass. What should I do?
I want something like this but it is not allowed in VB.NET
Public MustInherit Class GenericClass
Public Sub New(Byval x as Integer)
' Some code here
End Sub
Public Shared Function magicFunction(Byval y as Integer) as GenericClass
Dim z as Integer
' Some code here that will alter the value of z
Return New GenericClass(z) ' Not allowed in VB.NET -- MustInherit class cannot have new
End Sub
End Class
Calling the magicFunction of the inheriting SpecificClass should return an object of SpecificClass like this:
Public Class ABC
Public Function myAwesomeFunction as SpecificClass
Dim objSpecificClass as SpecificClass
objSpecificClass = SpecificClass.magicFunction(someInteger)
Return objSpecificClass
End Sub
End Class
Any help would be appreciated
This may help:
Public MustInherit Class GenericClass(Of T As {GenericClass(Of T)})
Public Sub New(ByVal x As Integer)
' Some code here
End Sub
Public Shared Function magicFunction(ByVal y As Integer) As GenericClass(Of T)
Dim z As Integer
' Some code here that will alter the value of z
Return Activator.CreateInstance(GetType(T), z)
End Function
End Class
Public Class SpecificClass1
Inherits GenericClass(Of SpecificClass1)
Public Sub New(ByVal x As Integer)
MyBase.New(x)
End Sub
End Class
Public Class SpecificClass2
Inherits GenericClass(Of SpecificClass2)
Public Sub New(ByVal x As Integer)
MyBase.New(x)
End Sub
End Class
Usage:
Dim a As SpecificClass1 = SpecificClass1.magicFunction(1)
Dim b As SpecificClass2 = SpecificClass2.magicFunction(2)
Please see the code below:
Public Class clsCar
Implements IVehicle
Public Function getWheels() As Integer Implements IVehicle.getWheels
Return 4
End Function
End Class
Public Interface IVehicle
Function getWheels() As Integer
End Interface
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim list As List(Of IVehicle) = New List(Of IVehicle)
Dim v1 As IVehicle = New clsCar
Dim v2 As IVehicle = New clsBus
list.Add(v1)
list.Add(v2)
Dim IVehicle As IVehicle = New clsCar
Dim IVehicle2 As IVehicle = New clsBus
For Each IVehicle In list
MsgBox(IVehicle.getWheels())
Next
End Sub
End Class
I want to add a new function to the clsBus class:
Public Function getWheels(ByVal strCarType As String) As Integer
If strCarType = "Robin Ryliant" Then
Return 3
Else
Return 4
End If
End Function
How do I call this from the FOR EACH statement? At the moment it will call getWheels with no arguments.
You will have to add the method overload to the interface in order to be able to call it from a IVehicle variable.
Public Interface IVehicle
Function getWheels() As Integer
Function getWheels(ByVal strCarType As String) As Integer
End Interface
But probably it is better to have different, more specialized car types
Public Class clsCar
Implements IVehicle
Public Overridable Function getWheels() As Integer Implements IVehicle.getWheels
Return 4
End Function
End Class
Public Class clsRobinRyliantCar
Inherits clsCar
Public Overrides Function getWheels() As Integer
Return 3
End Function
End Class
This does not break the inheritance hierarchy and is purely polymorphic.
I think I would go for something more like this, with the number of wheels being an instance property (code in LINQPad format):
Sub Main
Dim list As List(Of IVehicle) = New List(Of IVehicle)()
list.Add(New clsCar("Ford Focus", 4))
list.Add(New clsCar("Robin Ryliant", 3))
list.Add(New clsBus())
For Each v In list
Console.WriteLine(String.Format("{0}:{1}", v.GetVehicleType(), v.GetWheels()))
Next
End Sub
' Define other methods and classes here
Public Interface IVehicle
Function GetVehicleType() As String
Function GetWheels() As Integer
End Interface
Public MustInherit Class clsVehicle
Implements IVehicle
Protected Property VehicleType As String
Protected Property Wheels As Integer
Protected Sub New(vehicleType As String, wheels As Integer)
Me.VehicleType = vehicleType
Me.Wheels = wheels
End Sub
Public Function GetVehicleType() As String Implements IVehicle.GetVehicleType
Return Me.VehicleType
End Function
Public Function GetWheels() As Integer Implements IVehicle.GetWheels
Return Me.Wheels
End Function
End Class
Public Class clsCar
Inherits clsVehicle
Public Sub New(vehicleType As String, wheels As Integer)
MyBase.New(vehicleType, wheels)
End Sub
End Class
Public Class clsBus
Inherits clsVehicle
Public Sub New()
MyBase.New("Bus", 4)
End Sub
End Class
If your clsBus and clsCar are meant to refer to a specific car then the type should be a member of that class already, not something you pass in when you want to get information. To this end I'd suggest that you have "type" as something you can pass in the constructor and then the method on the bus would have no parameters and would just refer to its internal type to determine how many wheels it has.
I'm not too fluent with VB.NET so would probably make mistakes in example code but hopefully you get what I mean. If not I'll knock up some code. :)
Say I have a class with several methods within it. I want to organize the methods into groupings that can be accessed without constructing a new object each time. The purpose is to group the methods of the class into logical buckets
For instance:
Dim myclass as MyCustomClass
myclass.Shipping.Get_List()
myclass.Production.Get_List()
What is the best way to do this? I tried nested classes, but VB.NET won't let me access the methods as shown above.
so this is how i would do what you want
this is not the best design of the world but it would work
I would suggest you to move the actual get_list and other kind of method / property into the specific class while keeping the common one in the parent class, which in this case is test
but then, I have no idea what your code look like so from that point on, it's your choice
Module Module1
Sub Main()
Dim test As New test
test.Production.Get_List()
test.Shipping.Get_List()
End Sub
End Module
Public Class Shipping
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetShipping_List
End Function
End Class
Public Class Production
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetProduction_List
End Function
End Class
Public Class test
Public Property Production As Production
Public Property Shipping As Shipping
Public Function GetShipping_List() As List(Of Integer)
Return Nothing
End Function
Public Function GetProduction_List() As List(Of Integer)
Return Nothing
End Function
Public Sub New()
Production = New Production(Me)
Shipping = New Shipping(Me)
End Sub
End Class
With caution that you more than likely should re-evaluate your architecture, you could implement your pattern like this:
Public Class MyCustomClass
Private _shippingList As List(Of String)
Private _productionList As List(Of String)
Public Production As ProductionClass
Public Shipping As ShippingClass
Public Sub New()
Production = New ProductionClass(Me)
Shipping = New ShippingClass(Me)
End Sub
Public Class ShippingClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
Public Class ProductionClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
End Class
However, if your true intent is simply organizing the methods in a more accessible and logical manner, I would suggest considering:
Public Class MyCustomClass
Public Sub ShippingListGet()
End Sub
Public Sub ShippingListAddTo()
End Sub
Public Sub ShippingThatDO()
End Sub
Public Sub ShippingThisDo()
End Sub
Public Sub ProductionListGet()
End Sub
Public Sub ProductionListAddTo()
End Sub
Public Sub ProductionThisDo()
End Sub
Public Sub ProductionThatDo()
End Sub
End Class
Keep in mind, some people consider that difficult to read. I personally prefer organization along those lines so when the methods are sorted alphabetically they group logically.
I have found the solution I was looking for using interfaces
Public Interface ICompany
Function Company_List() As DataTable
End Interface
Public Class MainClass
Public Company As ICompany = New CompanyClass
Public Sub New()
MyBase.New()
End Sub
Private Class CompanyClass
Public Sub New()
MyBase.New()
End Sub
Public Function Company_List() As DataTable
My code....
End Function
End Class
End Class