vb.net: override toString method for enums - vb.net

I would like to override toString method for each enum value. For example, I know in Java it can be done as below:
public enum Language_Culture_Names{
English {
#Override
public String toString() {
return "en-GB";
}
},
Spanish {
#Override
public String toString() {
return "es-ES";
}
},
Catalan {
#Override
public String toString() {
return "ca-ES";
}
}
}
System.out.println(Language_Culture_Names.English); -> returns en-GB
System.out.println(Language_Culture_Names.Spanish); -> returns es-ES
System.out.println(Language_Culture_Names.Catalan); -> returns ca-ES
So how to do this in VB.NET?

Ideally you should use a Class customized for yourself, since Enums are numeric constants and not string constants.
However, if you must use Enum and are looking for a generic solution, this is how I would do it:
First, add a Module to your project, with the following code:
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Module Module1
<Extension()> _
Public Function ToString2(ByVal EnumConstant As [Enum]) As String
Dim fi As Reflection.FieldInfo = EnumConstant.GetType().GetField(EnumConstant.ToString())
Dim aattr() As DescriptionAttribute = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
If aattr.Length > 0 Then
Return aattr(0).Description
Else
Return EnumConstant.ToString()
End If
End Function
End Module
We name our function ToString2 because Enum.ToString already exists, and can't be overridden. You can name it anything else.
Now in your class where the Enum is declared, decorate the Enum Members with Description attribute:
Imports System.ComponentModel '<-- be sure to include this Namespace
Public Enum Language_Culture_Names
<Description("en-GB")> English = 1
<Description("es-ES")> Spanish = 2
<Description("ca-ES")> Catalan = 3
End Enum
And finally dump the Enum.ToString method and use our new Enum.ToString2 method instead.
e.g.
TextBox1.Text = Language_Culture_Names.English.ToString2()
HTH.

Finally I have used type-safe-enum Pattern as below:
Public NotInheritable Class LanguageCultureNames
Private ReadOnly name As String
Private ReadOnly value As Integer
Public Shared ReadOnly English As New LanguageCultureNames(0, "en-GB")
Public Shared ReadOnly Spanish As New LanguageCultureNames(1, "es-ES")
Public Shared ReadOnly Catalan As New LanguageCultureNames(2, "ca-ES")
Private Sub New(ByVal value As Integer, ByVal name As String)
Me.name = name
Me.value = value
End Sub
Public Overrides Function ToString() As String
Return name
End Function
End Class

Related

VB if base class implements interface, does the derived class also need to implement?

I was analyzing a code. There we have a base class (not abstract) implementing an interface. Then we have a derived class of the base class which also implements the interface.
Interface:
Public Interface MainInterface
Function getMetaThreads(ByVal ThreadCount As Integer) As String()
Property Name() As String
Property TargetDirectory() As String
Property TimeOut() As Long
ReadOnly Property ExecutableAssembly() As String
ReadOnly Property IsVersionValid() As Boolean
End Interface
Base class:
Public Class BaseClass
Implements MainInterface
Public Sub print()
Console.WriteLine("BaseClass printing")
End Sub
Public ReadOnly Property ExecutableAssembly As String Implements MainInterface.ExecutableAssembly
...
End Property
Public ReadOnly Property IsVersionValid As Boolean Implements MainInterface.IsVersionValid
...
End Property
Protected strName As String = ""
Protected strTargetDirectory As String = ""
Protected lngTimeout As Long = 0
Public Property Name As String Implements MainInterface.Name
...
End Property
Public Property TargetDirectory As String Implements MainInterface.TargetDirectory
...
End Property
Public Property TimeOut As Long Implements MainInterface.TimeOut
...
End Property
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
...
End Function
Public Overridable Function myOwnFunc() As String
Return ""
End Function
End Class
Derived Class:
Public Class SubClass
Inherits BaseClass
Implements MainInterface
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
Return myOwnFunc()
End Function
Overrides Function myOwnFunc() As String()
Dim l As New List (Of String)
l.Add("44")
l.Add("33")
return l.ToArray()
End Function
End Class
Does it make sense to implement the interface in the derived class again? Is there a reason or a case where this becomes necessary? I think that having the base class implement the interface should be enough and implementing it in the interface is redundant.

Conversion of Object to another type of Object using TypeConverter in VB.Net

I am trying my best to understand the use of TypeConverters and how to use them.
Imports System.ComponentModel
Imports System.Globalization
<TypeConverter(GetType(OrderTypeConverter))>
Public Class OrderType1
Public Sub New()
Public Sub New(Order As OrderType2)
OrderNumber = Order.OrderNo
'Etc Etc
End Sub
Public Property OrderNumber As String
Public Property OrderDescription As String
End Class
Public Class OrderType2
Public Property OrderNo As String
Public Property Description As String
End Class
Public Class OrderTypeConverter
Inherits TypeConverter
Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean
If destinationType = GetType(OrderType2) Then
Return True
End If
Return MyBase.CanConvertTo(context, destinationType)
End Function
Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object
If destinationType = GetType(OrderType2) Then
Dim OldOrder As OrderType1 = DirectCast(value, OrderType1)
Dim NewOrder As New OrderType2
NewOrder.Description = OldOrder.OrderDescription
NewOrder.OrderNo = OldOrder.OrderNumber
Return NewOrder
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
I am not sure how to implement the conversion if the above is correct.
I know the alternative would be to pass an Order of OrderType2 into a new method of an Order Of OrderType1 and then go through all the properties etc etc but there has to be a better way

VB.NET - Access variable in class within class by string name

So here is part of my class structure:
Public Class CParticle
Public Feature As Double
Public AreaName As String
......
Public ElementsWT As SElements 'Elements in wt%
Public ElementsAT As SElements 'Elements in at%
Public Sub New()
ElementsWT = New SElements
ElementsAT = New SElements
End Sub
End Class
With this 'subclass':
Public Class SElements
Public B As Double
Public C As Double
Public N As Double
Public O As Double
Public F As Double
....
End Class
Now I want to access all variables within an instance of CParticle (e.g. called 'Particle') and also its instances of SElements by their name (String).
e.g.: "Feature" should give me access to Particle.Feature
Currently im doing it with reflection:
...
Dim myFieldInfo As FieldInfo
myFieldInfo = GetType(CParticle).GetField("Feature")
If Not myFieldInfo Is Nothing Then myFieldInfo.SetValue(Particle, value)
This works. But how can I access e.g. Particle.ElementsWT.B with the string "ElementsWT.B"? And is there an overall better way to do it besides using reflection?

Can a class's properties be assigned using a lookup, or must each property be assigned individually?

VS2013, Visual Basic
I have a class with many properties.
Public Class
Property 1
.
.
Property N
End Class
I have a list of name value pairs
name1, value1
.
.
nameN, valueN
The values in the name value pairs will be assigned to the property values.
Does VB have a way that allows me to take one of the names and use it to 'look up' the class property, select it an assign the value to it, looping through the name-value pairs to make all the assignments?
I didn't see a method attached to my Class as I defined it. Should I define my Class differently? I used the Class in the EF6 Code First method to create the backing database.
The alternative as I see it is to list each Class property one by one, looking up the name and assign the value, but that seems like a tedious way of doing things.
Just thought I would ask. Maybe there's a better way to do this.
Thanks.
Best Regards,
Alan
There are three classes which will help you; TypeDescriptor, PropertyDescriptor and PropertyDescriptorCollection. They are all located in the System.ComponentModel namespace.
Imports System.ComponentModel
We'll be using the following class for this example:
Public Class Foo
'Implements ICustomTypeDescriptor (Optional)
Public Property A() As String
Public Property B() As Date
Public Property C() As Integer
Public Property D() As Boolean
Public Overrides Function ToString() As String
Return String.Format("A='{0}', B='{1}', C='{2}', D='{3}'", Me.A, Me.B, Me.C, Me.D)
End Function
End Class
Get all the properties by invoking the static method GetProperties of the TypeDescriptor class. It returns a collection of PropertyDescriptor classes - your properties. Then you simply invoke either the SetValue and/or GetValue methods. Note that you can implement a custom type descriptor by implementing the ICustomTypeDescriptor interface.
Private Sub RunTest()
Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(Foo))
Dim ignoreCase As Boolean = True
Dim foo1 As New Foo()
properties.Find("A", ignoreCase).SetValue(foo1, "hello")
properties.Find("B", ignoreCase).SetValue(foo1, Date.Now)
properties.Find("C", ignoreCase).SetValue(foo1, 1234I)
properties.Find("D", ignoreCase).SetValue(foo1, True)
'Get property value:
'Dim a As String = CType(properties.Find("A", ignoreCase).GetValue(foo1), String)
Debug.WriteLine(foo1.ToString())
End Sub
Output: (immediate window)
A='hello', B='30.11.2014 11:14:39', C='1234', D='True'
Extension
To expand this even further one can create some extension methods.
Imports System.Runtime.CompilerServices
Public Module Extensions
<Extension()>
Public Function GetProperty(Of TComponent)(component As TComponent, propertyName As String, Optional ByVal ignoreCase As Boolean = True) As Object
Return TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).GetValue(component)
End Function
<Extension()>
Public Function GetProperty(Of TComponent, TValue)(component As TComponent, propertyName As String, Optional ByVal ignoreCase As Boolean = True) As TValue
Return CType(TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).GetValue(component), TValue)
End Function
<Extension()>
Public Sub SetProperty(Of TComponent)(instance As TComponent, propertyName As String, value As Object, Optional ByVal ignoreCase As Boolean = True)
TypeDescriptor.GetProperties(GetType(TComponent)).Find(propertyName, ignoreCase).SetValue(instance, value)
End Sub
End Module
Now it's very easy to set/get a property value by name.
Private Sub RunTest()
Dim foo1 As New Foo()
foo1.SetProperty("A", "hello")
foo1.SetProperty("B", Date.Now)
foo1.SetProperty("C", 1234I)
foo1.SetProperty("D", True)
'Get property value:
'Dim a As String = CType(foo1.GetProperty("A"), String)
'Dim a As String = foo1.GetProperty(Of String)("B")
Debug.WriteLine(foo1.ToString())
End Sub
Output:
A='hello', B='30.11.2014 11:18:17', C='1234', D='True'

Custom ASP.NET MVC2 HtmlHelper: How to get the instance of the object passed to it?

I am working on a ASP.NET MVC2 website. For learning. I am working with the Visual Basic language.
In a view I would like to do this:
<%: Html.EditorForEnumeracion(Function(v) v.combustible%>
So, I created an HtmlHelper extension method:
Imports System.Runtime.CompilerServices
Imports System.Linq.Expressions
Imports System.Reflection
Public Module HtmlHelpers
<Extension()> _
Public Function EditorForEnumeracion(Of TModel, TValue)(ByVal html As HtmlHelper(Of TModel), ByVal expression As Expression(Of Func(Of TModel, TValue))) As MvcHtmlString
'My stuff goes here
End Function
End Module
The problem is that I do not know how to get the instance of the v.combustible object that I pass to the helper. I do not care about the v object. I need to work with the combustible attribute of the v object.
Here and here seems to be how to do this, but I do not understand. Also, I work with Visual Basic, not C#.
I think that I can get the instance of the Enumeracion object through the expression parameter, but I do not understand how.
More info now.
This is my "Vehiculo" class:
Namespace Models.Automovil
Public Class Vehiculo
Public Property tipo As New Models.Enumeracion("TipoDeVehiculo")
Public Property marca As String
Public Property modelo As String
Public Property numeroDePuertas As Integer
Public Property combustible As New Models.Enumeracion("TipoDeCombustible")
Public Property potencia As Integer
Public Property fechaPrimeraMatriculacion As DateTime
Public Property version As String
Public Property precio As Decimal
Public Property descripcion As String
End Class
End Namespace
And this is my "Enumeracion" class:
Namespace Models
Public Class Enumeracion
Private bd As New tarificadorasegasaEntities
Private diccionario As New Dictionary(Of String, Integer)
Private _nombre As String
Private _clave As String
Private _valor As Integer
Public ReadOnly Property nombre As String
Get
Return _nombre
End Get
End Property
Public ReadOnly Property clave As String
Get
Return _clave
End Get
End Property
Public ReadOnly Property valor As Integer
Get
Return _valor
End Get
End Property
'More stuff here. Methods.
End Class
End Namespace
The model is the Vehiculo class.
Still not resolving this.
Thanks in advance.
You need to compile the expression into a Func(Of TModel, TValue), then call it on the model:
Dim func = expression.Compile()
Dim value = func(html.ViewData.Model)
Try like this:
<Extension()> _
Public Function EditorForMyCustomClassB(Of Vehiculo, Enumeracion)(ByVal html As HtmlHelper(Of TModel), ByVal expression As Expression(Of Func(Of Vehiculo, Enumeracion))) As MvcHtmlString
Dim res = ModelMetadata.FromLambdaExpression(expression, html.ViewData)
Dim e As Enumeracion = DirectCast(res.Model, Enumeracion)
' use e here
End Function