Sending Type Parameters like DirectCast - vb.net

I've made this extension to replace my usage of DirectCast, because i don't find it very readable.
<Extension>
Public Function [As](Of T)(Input As Object) As T
Return DirectCast(Input, T)
End Function
Dim i = (New Integer).As(Of Integer)
My problem is the need for "Of" before writing integer.
DirectCast doesn't need that.
DirectCast(New Integer, Integer)
How can i change my code to have the same appearance as DirectCast's type parameter?
Essentially looking like this:
Dim i = (New Integer).As(Integer)

Just use a normal function instead of an extension method:
Function ToInt(o As Object) As Integer
Return DirectCast(o, Integer)
End Function
The other option is to use the VB type conversion functions: MSDN link (Note, however, that they return new objects - they are not typecasting functions)
Though really, I'd recommend you stick to the built-in DirectCast function. All you are really doing is replacing a built-in keyword with a custom keyword that no-one else will recognise.

Related

Can't get a list of declared methods in a .net class

Having read a great many posts on using reflection to get a list of methods in a given class, I am still having trouble getting that list and need to ask for help. This is my current code:
Function GetClassMethods(ByVal theType As Type) As List(Of String)
Dim methodNames As New List(Of String)
For Each method In theType.GetMethods()
methodNames.Add(method.Name)
Next
Return methodNames
End Function
I call this method like this:
GetClassMethods(GetType(HomeController))
The return has 43 methods, but I only want the methods I wrote in the class. The image below shows the beginning of what was returned. My declared methods are in this list, but down at location 31-37. There are actually 9 declared methods, but this list doesn’t show the Private methods.
When I look at theType, I see the property I want. It is DeclaredMethods which shows every declared method, public and private.
However, I’m not able to access this property with a statement such as this.
Dim methodList = theType.DeclaredMethods
The returned error is that DelaredMethods is not a member of Type. So, my questions are multiple:
1) Most important, what code do I need to retrieve every declared method in the class, and only the methods I declared?
2) Why am I not able to access the property that gives the list of DeclaredMethods()?
Try this:
Function GetClassMethods(ByVal theType As Type) As List(Of String)
Dim flags = Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.DeclaredOnly
Dim result = theType.GetMethods(flags).
Where(Function(m) Not m.IsSpecialName).
Select(Function(m) m.Name)
Return result.ToList()
End Function
or for some fun with generics:
Function GetClassMethods(Of T)() As List(Of String)
Dim flags = Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.DeclaredOnly
Dim result = GetType(T).GetMethods(flags).
Where(Function(m) Not m.IsSpecialName).
Select(Function(m) m.Name)
Return result.ToList()
End Function
The IsSpecialName filter excludes methods with compiler-generated names, such as the special methods used by the compiler to implement properties. You can also play around more with the flags if you need to include, say, NonPublic members as well.
Finally, whenever you have a method ending with Return something.ToList() (or which could end with it, as my adaption shows here), it's almost always better to change the method to return an IEnumerable(Of T) instead, and let the calling code call ToList() if it really needs it. So my first example above is really better like this:
Function GetClassMethods(ByVal theType As Type) As IEnumerable(Of String)
Dim flags = Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.DeclaredOnly
Return theType.GetMethods(flags).
Where(Function(m) Not m.IsSpecialName).
Select(Function(m) m.Name)
End Function
Hey, that could be a single-liner. Then for those situations where you really need a list, you can do this:
Dim methodNames As List(Of String) = GetClassMethods(HomeController).ToList()
You'll start to find in many situations you don't need to use ToList() at all; the generic IEnumerable was good enough. Certainly this is true anywhere you just use the result with For Each loop. Now suddenly the memory use in your programs are significantly reduced.

BC42322 VB.NET Runtime errors might occur when converting 'String' to 'IFormatProvider'

I'm trying to migrate old VB6(Visual Basic 6.0) Project to VB.net framework 4.6x.
But I had to move to .net framework 2.0 first.
I used to convert numbers in TextBox to formatted numbers using ToString as below.
In Visual Studio 2017 .net framework 2.0, I have BC42322 warning.
Is there a way to solve this?
txtDividend.Text = txtDividend.Text.ToString("###,###,##0")
I also have
On Error GoTo Error_Handle
at the start of the function to handle characters in that textbox
The Text property is already a string, and the ToString() method for string doesn't have the overload you want.
Since it seems this same text field can hold both the formatted and unformatted version of a value, what you may want to do is first strip off any formatting, convert to a numeric type like Integer or Decimal, and then use the ToString() method from there:
Public Function FormatDividend(dividend As String) As String
Dim extraCharacters As New Regex("[^\d,.-]")
dividend = extraCharacters.Replace(dividend, "")
Return FormatDividend(CDec(dividend))
End Function
Public Function FormatDividend(dividend As Decimal) As String
Return Dividend.ToString("###,###,##0")
End Function
You can call those functions like this:
txtDividend.Text = FormatDividend(txtDividend.Text)
And of course you can tweak that expression however you want, or change the overload and cast to use Integer instead of Decimal.
Since you are trying to migrate from an environment where "1000".ToString("###,##0") produced 1,000, you will want that to work in your new (.net). That solution is to create an extension method that essentially provides the overload.
<Extension>
Function ToString(input as String, format as String) as String
Static numericOnly As Regex = New Regex("[^\d.-]")
Dim asDec as Decimal
Decimal.TryParse(numericOnly.Replace(input, ""), asDec)
Return asDec.ToString(format)
End Function
Since I have more than one TextBox to use format, I upgraded Joel Coehoorn's answer to use format TextBox in my project.
First, I created CommonFunction.vb module file
Imports System.Text.RegularExpressions
Module CommonFunction
Public Function FormatNumberInText(text As String, format As String) As String
Dim extraCharacters As New Regex("[^\d,.-]")
text = extraCharacters.Replace(text, "")
Return FormatNumberInText(CDec(text), format)
End Function
Public Function FormatNumberInText(text As Decimal, format As String) As String
Return text.ToString(format)
End Function
End Module
and in my TextBox vb file, I used it as below.
txtDividend.Text = FormatNumberInText(txtDividend.Text, "###,###,##0")
txtDividendRatio.Text = FormatNumberInText(txtDividendRatio.Text, "###,###,##0.0#")
Thank you Joel Coehoorn.
It appears that the ToString() Method is designed to convert other types to a string and format them as desired. It was not designed to format an existing string. The simplest way I have found around this problem is to convert your string into another data type and then apply the ToString() Method.
So in your case I would convert to a double using the CDbl() Method:
txtDividend.Text = CDbl(txtDividend.Text).ToString("###,###,##0")

How to set a generic return type

I read values from a cell and the return is not fix. Instead of writing many functions for each return type I try to write a function with a generic return type but I stuck with this:
Public Function GetValueFromCells(Of t)(ByVal CellName As String) As t
Return CType(_xlWorksheet.Range(CellName).Value2)
End Function
No matter what type I will find in the cell, I want to convert the value to the return type I set in the function. But all my attemps have been in vain. It would be great if anyone could help me get this accomplished.
It's been awhile since I touched VB.Net, but you should be able to do this:
Public Function GetValueFromCells(Of t)(ByVal CellName As String) As t
Return CType(_xlWorksheet.Range(CellName).Value2, t)
End Function
I would address a couple of things.
Use more descriptive Generic Type arguments and just declare a type of the Generic and return that.
Public Function GetValueFromCells(Of TCellValue)(ByVal cellName As String) As TCellValue
Dim specificValue As TCellValue = Nothing
specificValue = DirectCast(_xlWorksheet.Range(cellName).Value2, TCellValue)
Return specificValue
End Function

Convert method parameters into array

Is there a Visual Basic.NET method that can convert method parameters into an array?
For instance instead of:
Function functionName(param1 as object, param2 as object) as object
ArrayName = {param1, param2}
you could do something like:
Function functionName(param1 as object, param2 as object) as object
ArrayName = MethodThatGetsAllFunctionParams
Just curious really.
There is no way of doing that. The language itself doesn’t allow that. You can use reflection to get the currently executing method of the StackFrame of the execution. But even then it’s still impossible to retrieve the parameter values.
The only solution is to “patch” the applications by introducing point cuts into the method call. The linked answer mentions a possibility for that.
Take a look at ParamArrays. I think this solves what you're asking for?
http://msdn.microsoft.com/en-us/library/538f81ec%28v=VS.100%29.aspx
EDIT:
You could initialise a custom collection using your current function signature
Public Class CustomCollection(Of T)
Inherits System.Collections.Generic.List(Of T)
Sub New(param1 As T, param2 As T)
MyBase.New()
MyBase.Add(param1)
MyBase.Add(param2)
End Sub
End Class
and then call the function using
Dim result = functionName(New CustomCollection(Of Object)(param1, param2))
The Function signature would be changed to:
Public Function functionName(ByVal args As CustomCollection(Of Object)) As String

Writing a cache function in VB.NET

I'm still learing VB.NET and usually I just google my questions, but this time I really don't know what to look for so I'll try here.
Trying to write a function that takes the cache key as a parameter and returns the cached object. No problems there, but I can't figure out how to pass the type into the function to use with TryCast, so that I don't have to do that with the returned result.
Here is my function so far, the ??? is to be replaced with the type that is passed into the function somehow.
Public Function GetCache(ByVal tag As String) As Object
Dim obj As Object = Nothing
Dim curCache As Object = TryCast(System.Web.HttpContext.Current.Cache(tag), ???)
If Not IsNothing(curCache) Then
Return curCache
Else
Return Nothing
End If
End Function
Am I doing this completely wrong or am I just missing something?
Use a generic:
Public Function GetCache(Of T)(ByVal tag As String) As T
Return CType(System.Web.HttpContext.Current.Cache(tag), T)
End Function
update:
Edited to use CType, because trycast only works with reference types. However, this could throw an exception if the cast fails. You can either handle the exception, check the type before making the cast, or limit your code to reference types like this:
Public Function GetCache(Of T As Class)(ByVal tag As String) As T
Return TryCast(System.Web.HttpContext.Current.Cache(tag), T)
End Function