Declare Property as diferent Class based on other value - vb.net

I have: ClassUsser, ClassClient, ClassPerson.
ClassUsser
Public Property Name as String
ClassClient
Public Property Name as String
ClassPerson
Public Property KindPerson as Integer
Public Property Person as (ClassClient or ClassPerson)
I want delare Property Person as diferent type of class based on value of KindPerson.
Enum KindsPerson
{ User=1,
Client=2}
First, I would set value of KindPerson, and after, through set/get methods, obtain the Person
I don't Know If It si posible in VB.Net. It exists any way to do this?
Thanks

You could use the Factory Pattern:
Module Module1
Sub Main()
Dim p1 = Person.GetPerson(Person.PersonKind_ENUM.Client, "Adam")
Dim p2 = Person.GetPerson(Person.PersonKind_ENUM.User, "Barbara")
Dim personList As New List(Of Person)
personList.Add(p1)
personList.Add(p2)
For Each p In personList
Console.WriteLine($"{p.GetType.Name}: {p.name}")
Next
Console.ReadKey()
End Sub
Public Class User
Inherits Person
End Class
Public Class Client
Inherits Person
End Class
Public MustInherit Class Person
Property Name As String
Public Enum PersonKind_ENUM
User
Client
End Enum
Public Shared Function GetPerson(personKind As PersonKind_ENUM, name As String) As Person
Select Case personKind
Case PersonKind_ENUM.Client
Return New Client() With {.Name = name}
Case PersonKind_ENUM.User
Return New User() With {.Name = name}
Case Else
Throw New InvalidOperationException
End Select
End Function
End Class
End Module

Related

How to implement a class when it is defined in an interface?

An interface can have a class in it but I do not understand how to implement such an interface. I give an example below:
I wrote the following simple code without any interface:
Imports System
Module Program
Sub Main()
Dim n As New name("Mounisha", "Ghosh")
Dim student As New Student(n, 14)
Console.WriteLine("First Name: {0}", student.studentName.firstName)
Console.WriteLine("Last Name: {0}", student.studentName.lastName)
Console.WriteLine("Age: {0}", student.age)
Console.ReadLine()
End Sub
End Module
Class name
Public Property firstName As String
Public Property lastName As String
Sub New(ByVal f As String, ByVal l As String)
firstName = f
lastName = l
End Sub
End Class
Class Student
Private nameValue As name
Public ReadOnly Property studentName() As name
Get
Return nameValue
End Get
End Property
Public Property age As Integer
Sub New(ByVal n As name, ByVal a As Integer)
nameValue = n
age = a
End Sub
End Class
Then I tried to re-organize by putting the class name in an interface and implement it in the class student. But I was not able to construct my code. I give the overall idea of the code I am trying to construct below:
Imports System
Interface IClass
Class name
Public Property firstName As String
Public Property lastName As String
Sub New(ByVal f As String, ByVal l As String)
firstName = f
lastName = l
End Sub
End Class
End Interface
Module Program
Sub Main()
'How to create instances and pass values to constructors?
End Sub
End Module
Class Student : Implements IClass
'The idea is to create a readonly property of type "name"
'But not able to use the Interface to do the same
Public Property age As Integer
End Class
The main idea is to understand how to implement an interface with a class in it. Pls help.
The other point I want to highlight is that in the constructor of the class name I have written End Sub. Now we cannot use the end sub statement in interface - so why am I not getting an error? Also do the statements firstName = f and lastName = l not denote an implementation which should have been flagged as an error by the compiler - but not getting any error. Any explanations for this?
What you're doing is simply adding a nested class to the interface. This isn't seen as something that the implementing class has to implement but instead is just a class available via that interface. Using your structure, in order to require Student to implement a read only name property, you have to add that property to the interface.
Public Interface IClass
ReadOnly Property Fullname As Name
Class Name
Public Property FirstName As String
Public Property LastName As String
Sub New(firstName As String, lastName As String)
Me.FirstName = firstName
Me.LastName = lastName
End Sub
End Class
End Interface
Your Student Class would then look like
Public Class Student : Implements IClass
'Because Name is nested within IClass, it's referenced by IClass.Name
Public ReadOnly Property Fullname As IClass.Name Implements IClass.Fullname
Public Property Age As Integer
Public Sub New(name As IClass.Name, age As Integer)
Fullname = name
Me.Age = age
End Sub
End Class
And creating a student would be
Dim name = New IClass.Name("Mounisha", "Ghosh") 'again we access name via the interface
Dim student = New Student(name, 14)
Usually you would not add a nested Class to the interface but instead do something like
Module Program
Sub Main()
Dim studuent = New Student(New Name("Mounisha", "Ghosh"), 14)
End Sub
End Module
Interface IClass
ReadOnly Property Fullname As Name
End Interface
Public Class Name
Public Property FirstName As String
Public Property LastName As String
Sub New(firstName As String, lastName As String)
Me.FirstName = firstName
Me.LastName = lastName
End Sub
End Class
Class Student : Implements IClass
Public ReadOnly Property Fullname As Name Implements IClass.Fullname
Public Property Age As Integer
Public Sub New(name As Name, age As Integer)
Fullname = name
Me.Age = age
End Sub
End Class

Filter List of Class by Property Value and List Of Value

I have a Devexpress Gridcontrol bound to a custom class.
The class looks like this:
Public Class AuditList
Public CasualtyList As List(Of CasualtyRecords)
Public MedsList As List(Of CasualtyRecords.Medications)
Public Property FilterString As CriteriaOperator
Public Sub New()
CasualtyList = New List(Of CasualtyRecords)
MedsList = New List(Of CasualtyRecords.Medications)
End Sub
Public Class CasualtyRecords
Private _primary As New PS
Public Property PrimarySurvey As PS
Get
Return _primary
End Get
Set(value As PS)
_primary = value
End Set
End Property
Public Sub New()
Vitals = New List(Of VitalRecords)
End Sub
Public Property Vitals As List(Of VitalRecords)
Public Property Meds As List(Of Medications)
ReadOnly Property MedCount As Integer
Get
Return Meds.Count
End Get
End Property
Property Id As Integer
Property ClinicalImpression As String
Property Disposal As String
Property Age As Integer
Property Gender As String
Class PS
Public Property Airway As Integer
Public Property Breathing As Integer
Public Property Circulation As Integer
Public Property Rate As Integer
End Class
Class Medications
Public Property MedName As String
End Class
End Class
End Class
This is an example of a filter type I am trying to create:
"[Gender] ='Male' AND [Medications].[MedName] = 'Paracetamol' AND [Age] >100"
Is this possible with the class constructed as shown, or perhaps do I need to implement some other interface?
I imagine that it would look something like this with LINQ
Dim b As New CasualtyRecords
b = a.CasualtyList.Where(Function(x) x.Meds.Any(Medications.Med = "Paracetamol") And x.Gender = "Male" And x.Age > 20)
Thanks
I was able to achieve the required results using this LINQ query
Dim newrecords = a.CasualtyList.Where(
Function(x) x.Meds.Any(
Function(b) b.MedName = "Paracetamol") _
And x.Gender = "Male" And x.Age > 20).ToList()

Need Help Initializing a Generic Property in VB.Net

I've created a request class. Here is an abbreviated version of it:
Public Class Request(Of T)
Private _Account As String
Public Property Account() As String
Get
Return _Account
End Get
Set(ByVal value As String)
_Account = value
End Set
End Property
Private _InnerRequest As T
Public Property InnerRequest() As T
Get
Return Me._InnerRequest
End Get
Set(ByVal value As T)
Me._InnerRequest = value
End Set
End Property
End Class
And then I have two other classes that I intend to use with this one - again, abbreviated
Public Class Individual
Public FirstName As String
Public LastName As String
Friend Sub New()
End Sub
End Class
And
Public Class Commercial
Public EntityName As String
Friend Sub New()
End Sub
End Class
Again, both of these are pretty abbreviated. The issue comes in when I attempt to use the properties of individual or commercial:
Dim Req As New Request(Of Individual)()
Req.InnerRequest.FirstName = "Herman" <-- Null Ref Exception
So... how do I get my inner request null ref exception kicked? I tried simply using Me._InnerRequest = New T in the New sub of Request, but no dice. Is there a way to handle this?
Req.InnerRequest must be set to an object instance of Individual first.
Req.InnerRequest = new Individual()
Req.InnerRequest.FirstName = "Herman"
Or create an instance for InnerRequest with the following modifications
Public Class Request(Of T As {New}) 'Classes of type T must have a public new constructor defined
::
Private _InnerRequest As New T() 'Creates a new class of type T when an instance is created of Request
And make the constructors of the other classes Public instead of Friend.
Than you can directly do
Dim Req As New Request(Of Individual)()
Req.InnerRequest.FirstName = "Herman"
#Barry already answered what the main problem is, but here's an alternate syntax if you prefer object initializers:
Req.InnerRequest = new Individual() With { FirstName = "Herman" }
Or, if you prefer, you could overload the constructor for your Individual class:
Dim individual As New Individual("Herman")
Req.InnerRequest = individual
With the Individual class looking like:
Public Class Individual
Public FirstName As String
Public LastName As String
Friend Sub New()
End Sub
Friend Sub New(firstName As String)
Me.FirstName = firstName
End Sub
End Class
You probably should consider restricting the T to some Entity class:
Public Class Request(Of T As Entity)
From which both Individual and Commercial will inherit:
Public Class Individual : Inherits Entity
Then maybe declare an overridable property Name of type String on this Entity class (which can be abstract/MustInherit), this should provide some flexibility. Otherwise you'd be having a hard time consuming your design pattern.

there is any way to instantiate a new class based on enum?

there is any way to instantiate a new class based on enum through reflection?
Basicly i wanna to remove the Select Case. I have alot of Enum and builders....
For example:
Public MustInherit Class GeneralClass
'...
Enum GeneralClassType
A = 1
B = 2
End Enum
Public Shared Function BuildClass(Val as Integer, ParamArray par() as Object) as GeneralClass
Dim NewObject as GeneralClass = Nothing
Select Case Ctype(Val, GeneralClassType)
Case GeneralClassType.A
NewObject = new A
Case GeneralClassType.B
NewObject = new B
Case else
throw new exception("invalid type.")
end select
NewObject.setPar(par)
return NewObject
end function
End Class
Public Class A
Inherits GeneralClass
'...
End Class
Public Class B
Inherits GeneralClass
'...
End Class
The Function BuildClass build a class base on a type and parameters get from Database.
But i need to have the Case to create a new instance of a type.
I know i can instantiate a class through reflection, but only if you know the final type.
There is no way to do this dinamicy, like save the class name on database?
public function InstantiateClass(of T)() as T
Dim NewObject as GeneralClass = GetType(T).GetConstructor(New Type() {}).Invoke(New Object() {})
return NewObject
end class
than i can get something like
Dim Var1 as GeneralClass = InstantiateClass(of A)()
and use this instance inside the Build function. But here i need to know the Type A
BaseTest example, working with enum name.
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim BaseFlag As Integer = 2
Dim BaseName As String = "Create a class from enum"
Dim T As BaseTest = BaseTest.Build(BaseFlag, BaseName)
MsgBox(T.GetClassTypeName)
End Sub
End Class
Public MustInherit Class BaseTest
Protected Name As String
Enum TestType
TestA = 1
TestB = 2
TestC = 3
End Enum
Public Function GetClassTypeName() As String
Return String.Concat(Name, ". The final class is: ", Me.GetType.FullName, "")
End Function
Public Shared Function Build(BaseFlag As Integer, Name As String) As BaseTest
Dim NS As String = GetType(BaseTest).FullName
Dim Index As Integer = NS.LastIndexOf(".") + 1
NS = NS.Substring(0, Index)
Dim ClassType As String = CType(BaseFlag, TestType).ToString()
Dim Test As BaseTest = Activator.CreateInstance(Type.GetType(NS & ClassType))
Test.Name = Name
Return Test
End Function
End Class
Public Class TestB
Inherits BaseTest
End Class
The first step is to figure out how to get reflection to create an object instance given the class name as a string. Here's an example of one way to do that:
Dim o As Object = Activator.CreateInstance(Type.GetType("MyNameSpace.A"))
Once you have that working, all you need to do is to get the string name of the enumeration value. To do that, all you need to do is to call the ToString method on the enumeration object, for instance, in your case:
Dim className As String = CType(Val, GeneralClassType).ToString()
Once you have that, you can simply concatenate the class name to the namespace to create the object:
Dim o As Object = Activator.CreateInstance(Type.GetType("MyNameSpace." & className))
The example you posted is type-safe, whereas using reflection, like this, is not. Also, reflection can be a bit slower. You need to decide, based on your particular situation, whether or not it is worth giving up that type-safety and efficiency.

Generic Collections, Member Classes, Design Pattern question for VB.NET

I have a class called Person:
Public Class Person
Private PersonID as String
Private Name as String
Private Records as GenericCollection(Of PublicRecord)
Public Sub New(ByVal ID as String)
Me.PersonID = ID
Me.Name = getPersonName(ID)
End Sub
'Get/Sets
End Class
getPersonName is simply a function that does exactly as it is described. GenericCollection class is as follows:
Public Class GenericCollection(Of ItemType)
Inherits CollectionBase
' Purpose: Provides a generic collection class from which all other collections
' classes can be inherited if they wish to extend the functionality below.
#Region "Public Methods"
Public Function Add(ByVal NewObject As ItemType) As Integer
Return MyBase.InnerList.Add(NewObject)
End Function
Public Sub New()
MyBase.New()
End Sub
#End Region
#Region "Public Properties"
Default Public Property Item(ByVal Index As Integer) As ItemType
Get
Return CType(MyBase.InnerList(Index), ItemType)
End Get
Set(ByVal value As ItemType)
MyBase.InnerList(Index) = value
End Set
End Property
#End Region
End Class
PublicRecord class is:
Public Class PublicRecord
Private RecordID As String
Private RecordDataOne As String
Private RecordDataTwo As String
Public Sub New()
MyBase.New()
End Sub
'Get/Sets
End Class
One of the requirements I've been told can be done is that I should be able to grab all Persons in a Collection of Persons, then since all of those Persons will have Collectinos of Records within them... grab a specific set of data from the Collection of Records.
We'll say, I want to: getPersonsOverAge21() from the Collection of Records inside each Person inside the Collection of Persons.
Is this even possible? If so, can someone explain how it would work?
There's no need to implement your own generic collection class. .Net has already done this for you in the System.Collections.Generic namespace. Look at a List(Of Person) or even just a simple IEnumerable(Of Person).
Now you haven't explained how your record objects relate to your person type or what data they contain, so I can only speculate on the next part. But it sounds kind of like you want something like this:
Dim people As List(Of Person) = GetPeopleFromDatabase()
Dim peopleOver21 As IEnumerable(Of Person) = people.Where(Function(p) p.Age >= 21)
Dim peopleOver21Query = From p In people _
Where (p.Age >= 21) _
Select p