如何在c#中使用反射从方法调用的方法列表

本文关键字:方法 调用 列表 反射 | 更新日期: 2023-09-27 18:12:32

如何从c# (DotNet)中使用反射的方法调用方法列表或如何检查Method1是否使用反射从Method2调用?

如何在c#中使用反射从方法调用的方法列表

正如其他人指出的那样,使用反射基本上不可能做到这一点。为了找到调用,您必须自己解析方法的IL字节代码。幸运的是,有一个名为Mono Cecil(也可以在nuget上找到)的漂亮项目为您完成了所有艰苦的工作。这里有一个简单的例子来说明如何使用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 }));
    }
}