【问题标题】:How to get the list of methods called from a method using reflection in C#如何在 C# 中使用反射获取从方法调用的方法列表
【发布时间】:2020-04-14 17:23:26
【问题描述】:

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

【问题讨论】:

  • 你不能使用反射来做到这一点。反射旨在提供 元数据 - 您需要反编译器和/或代码分析来挖掘源代码。它可以告诉你房子的颜色、大小和地址,但不能告诉你里面有什么家具。你想达到什么目的?

标签: c# reflection system.reflection


【解决方案1】:

正如其他人指出的那样,使用反射基本上是不可能做到的。您必须自己解析方法的 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 }));
    }
}

【讨论】:

  • GetMethodsCalled 应该转换为MethodReference 而不是MethodDefinition
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 2011-07-25
相关资源
最近更新 更多