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

C# 如何在C中使用反射获取从方法调用的方法列表#,c#,reflection,system.reflection,C#,Reflection,System.reflection,如何获取在C#(DotNet)中使用反射的方法调用的方法列表,或者如何检查是否使用反射从方法2调用了方法1?正如其他人所指出的,使用反射基本上不可能做到这一点。为了找到调用,您必须自己解析方法的IL字节码。幸运的是,有一个名为(也可从上获得)的漂亮项目,它为您完成了所有的艰苦工作。这里有一个简单的例子来说明如何使用Mono Cecil解决您的问题: static class MethodDefinitionExtensions { public static bool CallsMeth

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

正如其他人所指出的,使用反射基本上不可能做到这一点。为了找到调用,您必须自己解析方法的IL字节码。幸运的是,有一个名为(也可从上获得)的漂亮项目,它为您完成了所有的艰苦工作。这里有一个简单的例子来说明如何使用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 }));
    }
}
静态类方法定义扩展
{
公共静态bool调用方法(此方法定义调用方,
方法定义(被调用方)
{
返回caller.Body.Instructions.Any(x=>
x、 操作码==操作码.Call&&x.操作数==被调用方);
}
}
班级计划
{
私有静态AssemblyDefinition\u assembly=AssemblyDefinition.ReadAssembly(
System.Reflection.Assembly.GetExecutionGassembly().Location);
私有静态void方法1()
{
方法2();
}
私有静态void方法2()
{
方法1();
方法3();
}
私有静态void方法3()
{
方法1();
}
私有静态IEnumerable GetMethodScaled(
方法定义(调用方)
{
返回caller.Body.Instructions
.Where(x=>x.OpCode==OpCode.Call)
.Select(x=>(MethodDefinition)x.Operand);
}
私有静态方法定义GetMethod(字符串名称)
{
TypeDefinition programType=\u assembly.MainModule.Types
.FirstOrDefault(x=>x.Name==“程序”);
首先返回programType.Methods(x=>x.Name==Name);
}
公共静态void Main(字符串[]args)
{
MethodDefinition method1=GetMethod(“method1”);
MethodDefinition method2=GetMethod(“method2”);
MethodDefinition method3=GetMethod(“method3”);
Debug.Assert(method1.CallsMethod(method3)=false);
Assert(method1.CallsMethod(method2)==true);
Assert(method3.CallsMethod(method1)==true);
Assert(getMethodScaled(method2).SequenceEqual(
新列表{method1,method3});
}
}

使用反射无法实现这一点。反射是为了提供元数据——您需要一个反编译器和/或代码分析来挖掘源代码。它可以告诉你房子的颜色、大小和地址,但不能告诉你里面有什么家具。你想达到什么目的?这有帮助吗
GetMethodScaled
应转换为
MethodReference
而不是
MethodDefinition