使用反射查看方法内部是否调用了方法
我正在使用反射,目前有一个 MethodBody。如何检查 MethodBody 内部是否调用了特定方法?
Assembly assembly = Assembly.Load("Module1");
Type type = assembly.GetType("Module1.ModuleInit");
MethodInfo mi = type.GetMethod("Initialize");
MethodBody mb = mi.GetMethodBody();
I'm working with reflection and currently have a MethodBody. How do I check if a specific method is called inside the MethodBody?
Assembly assembly = Assembly.Load("Module1");
Type type = assembly.GetType("Module1.ModuleInit");
MethodInfo mi = type.GetMethod("Initialize");
MethodBody mb = mi.GetMethodBody();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用Mono.Cecil。它是一个独立的程序集,可以在 Microsoft .NET 和 Mono 上运行。 (我想当我编写下面的代码时,我使用了 0.6 版或大约版本)
假设您有许多程序集
使用 AssemblyFactory 获取这些程序集(加载一个?)
以下代码片段将枚举这些程序集的所有类型中方法的所有用法
这将返回对方法的所有引用(因此包括在反射中使用,或构造可能执行或不执行的表达式)。因此,这可能不是很有用,只是向您展示无需太多努力即可使用 Cecil API 完成的操作 :)
请注意,此示例假定 Cecil 版本稍旧(主流单声道版本中的版本)。新版本
当然,在您的情况下,您可以将单个方法引用作为起点。假设您想检测何时可以在“startingpoint”内直接调用“mytargetmethod”实际上:
调用树搜索
这是一个工作片段,允许您递归搜索到相互调用的(选定的)方法(间接)。
注释
Resolve()
进行一些错误处理(我有一个扩展方法TryResolve()
用于此目的),MethodReferences
的用法仅调用操作(call、calli、callvirt ...)(参见//TODO
)典型用法:
注意函数的完成,例如检测请求使用情况满足您的需求完全取决于您(编辑:
Use Mono.Cecil. It is a single standalone assembly that will work on Microsoft .NET as well as Mono. (I think I used version 0.6 or thereabouts back when I wrote the code below)
Say you have a number of assemblies
Get these using AssemblyFactory (load one?)
The following snippet would enumerate all usages of methods in all types of these assemblies
This will return all references to methods (so including use in reflection, or to construct expressions which may or may not be executed). As such, this is probably not very useful, except to show you what can be done with the Cecil API without too much of an effort :)
Note that this sample assumes a somewhat older version of Cecil (the one in mainstream mono versions). Newer versions are
Of course in your case you could have a single method reference as starting point. Say you want to detect when 'mytargetmethod' can actually be called directly inside 'startingpoint':
Call Tree Search
Here is a working snippet that allows you to recursively search to (selected) methods that call each other (indirectly).
Notes
Resolve()
(I have an extension methodTryResolve()
for the purpose)MethodReferences
in a call operation (call, calli, callvirt ...) only (see//TODO
)Typical usage:
Note the completiion of a function like DetectRequestUsage to suite your needs is completely and entirely up to you (edit: but see here). You can do whatever you want, and don't forget: you'll have the complete statically analyzed call stack at your disposal, so you actually can do pretty neat things with all that information!
。在某些情况下,捕获异常比阻止生成异常要便宜得多。这是一个很好的例子。您可以获得方法主体的 IL,但 Reflection 不是反汇编程序。反汇编程序也不是真正的解决方案,您可以反汇编整个调用树以实现您想要的行为。毕竟,主体中的方法调用本身可以调用方法等等。捕获编译 IL 时抖动抛出的异常要简单得多。
There are a few cases where catching an exception is way cheaper than preventing it from being generated. This is a prime example. You can get the IL for the method body but Reflection is not a disassembler. Nor is a disassembler a real fix, you'd have the disassemble the entire call tree to implement your desired behavior. After all, a method call in the body could itself call a method, etcetera. It is just much simpler to catch the exception that the jitter will throw when it compiles the IL.
可以使用 StackTrace 类:
可以调整 1 并确定您感兴趣的帧数。
One can use the StackTrace class:
The 1 can be adjusted and determines the number of frame you are interested in.