How to get the list of methods called from a method using reflection in C# (DotNet) or How can I check whether Method1 is called from Method2 using reflection?
Asked
Active
Viewed 3,143 times
7
-
2You can't do that using reflection. Reflection is meant to provide _metadata_ - you'd need a decompiler and/or code analysis to dig into source code. It can tell you the color, size, and address of a house, but not what furniture is inside. What are you trying to achieve? – D Stanley Jul 10 '14 at 15:49
-
is this helpful ? http://www.codeproject.com/Articles/14058/Parsing-the-IL-of-a-Method-Body – pm100 Jul 10 '14 at 15:58
1 Answers
14
As others have pointed out, this is essentially impossible to do using reflection. You'd have to parse the IL byte code of the methods yourself in order to find the calls. Luckily, there's a beautiful project going by the name of Mono Cecil (also available on nuget) that does all the hard work for you. Here's a minimal example to illustrate how your problem could be solved using Mono Cecil:
static class MethodDefinitionExtensions
{
public static bool CallsMethod(this MethodDefinition caller,
MethodDefinition callee)
{
return caller.Body.Instructions.Any(x =>
x.OpCode == OpCodes.Call && x.Operand == callee);
}
}
class Program
{
private static AssemblyDefinition _assembly = AssemblyDefinition.ReadAssembly(
System.Reflection.Assembly.GetExecutingAssembly().Location);
private static void Method1()
{
Method2();
}
private static void Method2()
{
Method1();
Method3();
}
private static void Method3()
{
Method1();
}
private static IEnumerable<MethodDefinition> GetMethodsCalled(
MethodDefinition caller)
{
return caller.Body.Instructions
.Where(x => x.OpCode == OpCodes.Call)
.Select(x => (MethodDefinition)x.Operand);
}
private static MethodDefinition GetMethod(string name)
{
TypeDefinition programType = _assembly.MainModule.Types
.FirstOrDefault(x => x.Name == "Program");
return programType.Methods.First(x => x.Name == name);
}
public static void Main(string[] args)
{
MethodDefinition method1 = GetMethod("Method1");
MethodDefinition method2 = GetMethod("Method2");
MethodDefinition method3 = GetMethod("Method3");
Debug.Assert(method1.CallsMethod(method3) == false);
Debug.Assert(method1.CallsMethod(method2) == true);
Debug.Assert(method3.CallsMethod(method1) == true);
Debug.Assert(GetMethodsCalled(method2).SequenceEqual(
new List<MethodDefinition> { method1, method3 }));
}
}

TC.
- 4,133
- 3
- 31
- 33
-
`GetMethodsCalled` should cast to `MethodReference` instead of to `MethodDefinition` – Jan Apr 14 '20 at 09:24
-
Is it also possible to check for the argument type with which the method is called? – Mr Patience Nov 30 '22 at 08:25