Writing a cache function in VB.NET - 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

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.

How to create an extension method for any type of Enum array in VB.Net

Below is the code I have but the method is not available on Enum arrays. I can't work out what I'm doing wrong. Note that I'm unable to test the line Array.ConvertAll until I have this method available on Enum arrays.
Public Module EnumExtensions
<Extension()>
Function ValuesToString(Source As [Enum]()) As String()
Dim EnumType = Source.GetType()
If Not EnumType.IsEnum Then Return Nothing
Return Array.ConvertAll(Source, Function(x) x.ToString)
End Function
End Module
As I said in my comment, you could just call Select and ToArray as needed. If you really want an extension though, you would need to make your method generic:
<Extension>
Public Function ToStrings(Of T)(source As T()) As String()
'If Not GetType(T).IsEnum Then
' Return Nothing
'End If
Return Array.ConvertAll(source, Function(e) e.ToString())
End Function
There's no generic constraint that can limit that method to be called on just an array of Enum values so you can use an If statement to either return Nothing or throw an exception. I don't really see the point though, as it really doesn't hurt if you allow the same method to be called on another array of any other type anyway.

Sending Type Parameters like DirectCast

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.

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