Req15: GetType for instances, methods and properties
[This post is part of a series, "wish-list for future versions of VB"]
IDEA: GetType should work on instances.
' Currently we can get the System.Type of a named type
Dim t As Type = GetType(IEnumerable(Of ))
' We'd also like to get the compile-time System.Type of a given expression
Dim x As IEnumerable(Of Integer) = {1, 2, 3}
Dim t1 As Type = GetType(x) ' returns IEnumerable(Of Integer), the compile-time type
Dim t2 As Type = x.GetType() ' returns Integer(), the run-time type
' this doesn't evaluate the expression: it merely figures out its compile-time type:
Dim t As Type = GetType(New C)
Dim t As Type = GetType(Me) ' returns the compile-time type of "Me"
Dim t As Type = GetType(MyClass) ' for shared methods, returns the type of the class/module we're in
IDEA: GetType should be able to return stuff about a given method/property, or the current method/property. For instance,
' We'd also like to get the Reflection.MethodInfo of a specified method
Dim m As Reflection.MethodInfo = GetType(AddressOf Console.WriteLine(x))
' The expression isn't evaluated: it's merely used to resolve which overload
Dim m As Reflection.MethodInfo = GetType(AddressOf Call (New C).f(15 * Factorial(2)))
' A common need is to get the name of the current method
Dim m As Reflection.MethodInfo = GetType(AddressOf MyMethod)
' Likewise for properties, events, fields
Dim p As Reflection.PropertyInfo = GetType(AddressOf c.p)
Dim e As Reflection.EventInfo = GetType(AddressOf c.e)
Dim f As Reflection.FieldInfo = GetType(AddressOf c.f)
' And the current property:
Dim m As Reflection.MethodInfo = GetType(AddressOf MyProperty)
This idea has been frequently discussed and requested, e.g. here in Eric Lippert's blog. What has sunk the idea every single time is that getting a decent syntax for the feature is just so hard. One of the big problems with syntax is overloads, as in the Console.WriteLine example above. One approach is to invent a wholly new syntax which lets you write method signatures inside the GetType operator. Another approach, as I've taken here, is to write just a normal invocation expression -- except it's not invoked; it's merely used as a well-understood syntax for specifying which overload we want.
But all of the above examples can already be implemented today with a fairly decent workaround and recognizable syntax:
Dim minfo = GetMethodInfo(Sub() f())
Dim pinfo = GetPropertyInfo(Function() p)
Dim tinfo = GetTypeInfo(Me)
Dim current_minfo = Reflection.MethodBase.GetCurrentMethod()
Dim current_pinfo = GetPropertyInfo(Reflection.MethodBase.GetCurrentMethod())
Function GetMethodInfo(f As Expressions.Expression(Of Action)) As Reflection.MethodInfo
Return DirectCast(f.Body, Expressions.MethodCallExpression).Method
End Function
Function GetPropertyInfo(Of T)(ByVal f As Expressions.Expression(Of Func(Of T))) As Reflection.MemberInfo
Return DirectCast(f.Body, Expressions.MemberExpression).Member
End Function
Function GetPropertyInfo(ByVal minfo As Reflection.MemberInfo) As Reflection.PropertyInfo
Return (From p In minfo.DeclaringType.GetProperties() Where p.GetAccessors().Contains(minfo)).FirstOrDefault
End Function
Function GetTypeInfo(Of T)(ByVal x As T) As System.Type
Return GetType(T)
End Function
Provisional evaluation from VB team: The current workarounds do everything that's needed, and their syntax is familiar. There doesn't seem need to invent any new syntax for this. If anything, the Power6: __CALLER_MEMBER__ idea was neater than any of these proposals.