我想通过多个程序集找出特定方法的所有上游调用者。
我不需要解析后期绑定引用或虚方法调用,简单直接的CIL call
引用就可以了。
我看了几个选项:
CallGraph
类需要运行FxCop上下文。我想我的唯一解决方案是通过迭代程序集中的每个方法来向后工作,查找我的源方法的call
指令,然后递归地为每个调用方法重复该过程。
假设我提出的解决方案是可行的方法,那么最好的方法是什么? MethodInfo.GetMethodBody().GetILAsByteArray()
似乎有点硬。是否有任何库使得使用CIL(如ASM for Java)变得简单?
答案 0 :(得分: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;
答案 1 :(得分:-1)
我建议使用Roslyn。 以前从StackOverflow链接的是svick在MSDN上的答案: http://social.msdn.microsoft.com/Forums/vstudio/en-US/85a816cb-e931-4b49-893a-abbbf38c7a38/can-i-get-function-callercallee-information-from-roslyn
这是副本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);