Can you programmatically retrieve method information, without knowing the container?

ikantspelwurdz

Well-known member
Joined
Dec 8, 2009
Messages
49
Programming Experience
1-3
Take this code:
VB.NET:
        Dim s As String = Foo(AddressOf MsgBox)
        Console.WriteLine(s)

I would like this to print information about the method.

This would be good output:
Member of Microsoft.VisualBasic.Interaction

This would be even better output:
Assembly Microsoft.VisualBasic
C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Microsoft.VisualBasic.dll


The class MethodInfo looks promising, but is there a way to construct it from the method itself, not from the containing type? All the samples I found look like this:
VB.NET:
        Dim mi() As MethodInfo = GetType(Microsoft.VisualBasic.Interaction).GetMethods()
        Console.WriteLine("")
...and that doesn't help me, because I don't know that "Microsoft.VisualBasic.Interaction" is the name of the containing type.
 
Found something that works sometimes, but not always.

This:
VB.NET:
        Dim a As Action = AddressOf Console.WriteLine
        Dim mi As MethodInfo = a.Method
        Console.WriteLine(mi.DeclaringType.FullName)
        Console.WriteLine(mi.ReflectedType.Assembly.Location)

Will output this:
System.Console
C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll


This is good.

But it doesn't work with most functions, including the one I want. This:
VB.NET:
        Dim a As Action = AddressOf Console.ReadLine
        Dim mi As MethodInfo = a.Method
        Console.WriteLine(mi.DeclaringType.FullName)
        Console.WriteLine(mi.ReflectedType.Assembly.Location)

outputs this:
Project1.Module1
C:\Users\MyUserName\documents\visual studio 2013\Projects\Project1\Project1\bin\Debug\Project1.exe


This is bad.

Am I doing something wrong?
 
But it doesn't work with most functions, including the one I want. This:
Code:
Dim a As Action = AddressOf Console.ReadLine
For this to work you have to use a compatible delegate, there is no single delegate type that can match any method definition. Action delegate is defined (Public Delegate Sub Action) and will only match methods that has no parameters and returns no value. The strange output you got is due to the compiler generating a method in current project assembly to meet the relaxed delegate conversion.

Console.ReadLine() is defined: Public Shared Function ReadLine As String
So a compatible delegate for it could be Func(Of T) where T is the return type (String), and you get:
Dim a As Func(Of String) = AddressOf Console.ReadLine

Now you can get information from that delegate instance.
 
Thanks, that worked for Console.Readline. What about MsgBox? I'm getting stumped on this one.

MsgBox has this signature:
Public Function MsgBox(Prompt As Object, Optional Buttons As Microsoft.VisualBasic.MsgBoxStyle = OkOnly, Optional Title As Object = Nothing) As Microsoft.VisualBasic.MsgBoxResult

I tried this:
VB.NET:
                Dim a As Func(Of MsgBoxResult) = AddressOf MsgBox
        Dim mi As MethodInfo = a.Method
        Console.WriteLine(mi.DeclaringType.FullName)
        Console.WriteLine(mi.ReflectedType.Assembly.Location)

But that does not compile. It says:
Method 'Public Function MsgBox(Prompt As Object, [Buttons As MsgBoxStyle = MsgBoxStyle.OkOnly], [Title As Object = Nothing]) As MsgBoxResult' does not have a signature compatible with delegate 'Delegate Function Func(Of Microsoft.VisualBasic.MsgBoxResult)() As Microsoft.VisualBasic.MsgBoxResult'.

And if I do this:
VB.NET:
                Dim a As Func(Of Object, MsgBoxResult) = AddressOf MsgBox
        Dim mi As MethodInfo = a.Method
        Console.WriteLine(mi.DeclaringType.FullName)
        Console.WriteLine(mi.ReflectedType.Assembly.Location)
then I get the project assembly information again.

I've tried a handful of permutations of parameter types, return types, including optional parameters, and excluding optional parameters, but everything I tried either fails to compile, or gives me the project assembly info.
 
A Func(Of T1, T2, T3, Tresult) delegate would fit that signature:
Dim a As Func(Of Object, MsgBoxStyle, Object, MsgBoxResult) = AddressOf MsgBox
 
Thanks, that worked!

I made some headway on the REAL problem, but ran into a new roadblock.

I ran this code:
VB.NET:
Dim a As Func(Of Object, Object) = AddressOf MysteryFunction
Dim mi As MethodInfo = a.Method
msgbox(mi.DeclaringType.FullName)
msgbox(mi.ReflectedType.Assembly.Location)
msgbox(mi.Module.Name)

It is knowable that MysteryFunction has this signature:
Public Function MysteryFunction(o as Object) As Object

The first message box shows me this:
MysteryCompany.Scripting.MysteryCompanyScript

This is good!

But the second message box shows NOTHING.

And the third says <Unknown>.

Am I stuck? I'm not sure if there's anything else that's useful I can expose about MysteryFunction.

FYI, I cannot use Intellisense. I am not using Visual Studio. I am using a scripting tool created by Mystery Company. It accepts and executes standard VB.NET code, and there are a host of functions you can use in the code, but it gives me little information about any of them. At first I thought these functions were hiding inside a .NET DLL, like normal functions do, and if I could just identify the DLL I could reference it in Visual Studio and get my Object Explorer. But I'm starting to think that this isn't the case.
 
This is the first time I've heard of an assembly being loaded from a byte array, and not from a DLL file.

If this is the case, is there any way to retrieve this assembly's metadata? Or am I at a dead end?
 
Back
Top