1

我想通过多个程序集找出特定方法的所有上游调用者。

我不需要解析后期绑定引用或虚拟方法调用,简单直接的 CILcall引用就可以了。

我看过几个选项:

  • 反射器:工具的分析器部分不作为扩展点公开。
  • FxCop:CallGraph该类需要在其中运行 FxCop 上下文。
  • Roslyn:我不知道从哪里开始,但无论如何我对从源代码开始不感兴趣,我想给它一个程序集并使用字节码和元数据来代替。
  • VS 插件:与反射器一样,调用层次结构工具不会向插件公开。

我想我唯一的解决方案是通过迭代程序集中的每个方法来向后工作,寻找call我的源方法的指令,然后递归地为每个调用者方法重复该过程。

假设我提出的解决方案是可行的方法,那么最好的方法是什么?MethodInfo.GetMethodBody().GetILAsByteArray()好像有点硬核。是否有任何库可以让 CIL 的使用变得简单(比如 Java 的 ASM)?

4

2 回答 2

2

您可以使用Mono Cecil。为此,它与反射基本相同,只是它也会为您解析方法体。

执行此操作的代码草图:

var assembly = AssemblyDefinition.ReadAssembly(assemblyPath);
var methods = from module in assembly.Modules
              from type in module.Types
              from method in type.Methods
              from instruction in method.Body.Instructions
              where instruction.OpCode == OpCodes.Call
                    || instruction.OpCode == OpCodes.Callvirt
              let calledMethod = (MethodReference)instruction.Operand
              where calledMethod.DeclaringType.Name == givenMethodTypeName
                    && calledMethod.Name == givenMethodName
              select method;
于 2013-09-13T22:59:28.217 回答
-1

我建议使用罗斯林。以前从 StackOverflow 链接的是 svick 在 MSDN 上的答案:http: //social.msdn.microsoft.com/Forums/vstudio/en-US/85a816cb-e931-4b49-893a-abbbf38c7a38/can-i-get-function-callercallee -来自罗斯林的信息

这是复制 svick 的答案: var syntaxTree = SyntaxTree.ParseCompilationUnit(code);

var semanticModel = Compilation.Create("compilation")
    .AddSyntaxTrees(syntaxTree)
    .AddReferences(new AssemblyFileReference(typeof(object).Assembly.Location))
    .GetSemanticModel(syntaxTree);

var baz = syntaxTree.Root
    .DescendentNodes()
    .OfType<ClassDeclarationSyntax>()
    .Single(m => m.Identifier.ValueText == "C1")
    .ChildNodes()
    .OfType<MethodDeclarationSyntax>()
    .Single(m => m.Identifier.ValueText == "Baz");

var bazSymbol = semanticModel.GetDeclaredSymbol(baz);

var invocations = syntaxTree.Root
    .DescendentNodes()
    .OfType<InvocationExpressionSyntax>();

var bazInvocations = invocations
    .Where(i => semanticModel.GetSemanticInfo(i).Symbol == bazSymbol);
于 2013-09-13T20:43:42.787 回答