[See link above] Attached find sample source demonstrating use of Haibo Luo's ILReader.
ILReader is a C# assembly (source also included) which uses System.Reflection.MethodBase.GetMethodBody() to enumerate the instructions in a MethodBody.
ILReader implements a Visitor pattern, plus 17 small classes, each wrapping the information for one MSIL instruction type.
This F# sample adapts that Visitor pattern into a more natural F# idiom: a sequence whose elements are ILInstructionDU, which is a Discriminated Union with 17 alternatives. The main function is "seqInstructions : System.Reflection.MethodBase -> System.Collections.Generic.List<ILInstructionDU>"
Then the sample uses seqInstructions to find all the System.Reflection.Methods referenced by the EntryPoint of the currently executing assembly; e.g. the Main of this example itself. Note that Methods includes constructors and property accessors. Here is the key code:
let keepMethods ilDU =
match ilDU with
| Method m -> (Some m.Method)
| _ -> None
let Main =
let asm = R.Assembly.GetExecutingAssembly()
let meth = asm.EntryPoint
let ins = seqInstructions meth
let ms = ins |> Seq.choose keepMethods |> Seq.to_array
To see the results, place a breakpoint on an instruction after the "let ms = ..." line, and then examine the resultant array, using Visual Studio's debugger. You should see something like this:
- ms {System.Reflection.MethodBase[14]} System.Reflection.MethodBase[]
+ [0] {System.Reflection.Assembly GetExecutingAssembly()} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [1] {System.Reflection.MethodInfo get_EntryPoint()} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [2] {System.Collections.Generic.List`1[Testilvisitor+ILInstructionDU] seqInstructions[MethodInfo](System.Reflection.MethodInfo)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [3] {Void .ctor()} System.Reflection.MethodBase {System.Reflection.RuntimeConstructorInfo}
+ [4] {System.Collections.Generic.IEnumerable`1[System.Reflection.MethodBase] choose[ILInstructionDU,MethodBase,List`1](Microsoft.FSharp.Core.FastFunc`2[Testilvisitor+ILInstructionDU,Microsoft.FSharp.Core.Option`1[System.Reflection.MethodBase]], System.Collections.Generic.List`1[Testilvisitor+ILInstructionDU])} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [5] {System.Reflection.MethodBase[] to_array[IEnumerable`1,MethodBase](System.Collections.Generic.IEnumerable`1[System.Reflection.MethodBase])} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+
{Int32 get_Length()} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [7] {Void pam[Int32](System.String, Int32)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+
{Int32 get_Count()} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [9] {Void pam[Int32](System.String, Int32)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [10] {Void .ctor(System.String)} System.Reflection.MethodBase {System.Reflection.RuntimeConstructorInfo}
+ [11] {Microsoft.FSharp.Core.Unit printf[Unit](Microsoft.FSharp.Text.Format`4[Microsoft.FSharp.Core.Unit,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [12] {System.ConsoleKeyInfo ReadKey(Boolean)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+ [13] {Void ignore[ConsoleKeyInfo](System.ConsoleKeyInfo)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
~TMSteve