获取 C# 方法体内使用的类型
有没有办法获取 C# 方法中使用的所有类型?
例如,
public int foo(string str)
{
Bar bar = new Bar();
string x = "test";
TEST t = bar.GetTEST();
}
将返回:Bar、string 和 TEST。
我现在能得到的只是使用 EnvDTE.CodeFunction 的方法正文文本。也许有比尝试解析这段代码更好的方法来实现它。
Is there a way to get all types used inside C# method?
For example,
public int foo(string str)
{
Bar bar = new Bar();
string x = "test";
TEST t = bar.GetTEST();
}
would return: Bar, string and TEST.
All I can get now is the method body text using EnvDTE.CodeFunction. Maybe there is a better way to achieve it than trying to parse this code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我将借此机会发布我所做的概念证明,因为有人告诉我这是不可能完成的 - 通过在这里和那里进行一些调整,扩展它以提取所有内容是相对微不足道的方法中引用的类型 - 对于它的大小和缺乏前言表示歉意,但它有一些评论:
I'm going to take this opportunity to post up a proof of concept I did because somebody told me it couldn't be done - with a bit of tweaking here and there, it'd be relatively trivial to extend this to extract out all referenced Types in a method - apologies for the size of it and the lack of a preface, but it's somewhat commented:
如果您可以访问此方法的 IL,您也许可以做一些合适的事情。也许看看开源项目 ILSpy 并看看您是否可以利用他们的任何工作。
If you can access the IL for this method, you might be able to do something suitable. Perhaps look at the open source project ILSpy and see whether you can leverage any of their work.
正如其他人提到的,如果您有 DLL,您可以使用类似于 的内容ILSpy 的分析功能(迭代程序集中的所有 IL 指令以查找对特定类型的引用)。
否则,如果不将文本解析为 C# 抽象语法树,并使用解析器,就无法做到这一点 - 解析器可以很好地理解代码的语义,以了解示例中的“Bar”是否确实是一个名称可以从该方法访问的类型(在其“使用”范围内),或者可能是方法的名称、成员字段等... SharpDevelop 包含一个 C# 解析器(称为“NRefactory”)并且还包含这样一个解析器,你可以看看通过查看此线程来追求该选项,但请注意,这是公平的使其正常工作所需的工作量。
As others have mentioned, if you had the DLL you could use something similar to what ILSpy does in its Analyze feature (iterating over all the IL instructions in the assembly to find references to a specific type).
Otherwise, there is no way to do it without parsing the text into a C# Abstract Syntax Tree, AND employing a Resolver - something that can understand the semantics of the code well enough to know if "Bar" in your example is indeed a name of a type that is accessible from that method (in its "using" scope), or perhaps the name of a method, member field, etc... SharpDevelop contains a C# parser (called "NRefactory") and also contains such a Resolver, you can look into pursuing that option by looking at this thread, but beware that it is a fair amount of work to set it up to work right.
我刚刚发布了
如何使用 Mono.Cecil 进行静态代码分析
,如下所示。我还展示了一个 CallTreeSearch 枚举器类,它可以静态分析调用树,查找某些有趣的事情并使用自定义提供的选择器函数生成结果,因此您可以将其插入“有效负载”逻辑,例如,
这省略了一些细节
IsBusinessCall
、IsConstructorCall
和TryResolve
因为这些都很简单,仅用作说明性希望有帮助
I just posted an extensive example of
how to use Mono.Cecil to do static code analysis
like this.I also show a CallTreeSearch enumerator class that can statically analyze call trees, looking for certain interesting things and generating results using a custom supplied selector function, so you can plug it with your 'payload' logic, e.g.
This leaves out a few details
IsBusinessCall
,IsConstructorCall
andTryResolve
as these are trivial and serve as illustrative onlyHope that helps
我能想到的最接近的是表达式树。请查看Microsoft 的文档。
然而它们非常有限,并且仅适用于简单表达式,而不适用于具有语句体的完整方法。
编辑:由于海报的目的是查找类耦合和使用的类型,我建议使用商业工具,例如 NDepend 将代码分析作为一个简单的解决方案。
The closest thing to that that I can think of are expression trees. Take a look at the documentation from Microsoft.
They are very limited however and only work on simple expressions and not full methods with statement bodies.
Edit: Since the intention of the poster was to find class couplings and used types, I would suggest using a commercial tool like NDepend to do the code analysis as an easy solution.
这绝对不能通过反射(GetMethod()、表达式树等)来完成。正如您所提到的,使用 EnvDTE 的 CodeModel 是一种选择,因为您可以逐行获取 C# 在那里,但在 Visual Studio 之外使用它(即处理已经存在的函数,而不是在编辑器窗口中)几乎是不可能的,恕我直言。
但我可以推荐Mono.Cecil,它可以处理CIL 逐行代码(在方法内),您可以在您引用的任何程序集中的任何方法上使用它。然后,您可以检查每一行是否是变量声明(例如 string x = "test" 或 methodCall),并且可以获得这些行中涉及的类型。
This definitely cannot be done from reflection (GetMethod(), Expression Trees, etc.). As you mentioned, using EnvDTE's CodeModel is an option since you get line-by-line C# there, but using it outside Visual Studio (that is, processing an already existing function, not in your editor window) is nigh-impossible, IMHO.
But I can recommend Mono.Cecil, which can process CIL code line-by-line (inside a method), and you can use it on any method from any assembly you have reference to. Then, you can check every line if it is a variable declaration (like string x = "test", or a methodCall, and you can get the types involved in those lines.
通过反射,您可以 获取方法。这将返回一个 MethodInfo 对象,通过该对象,您可以无法获取该方法中使用的类型。所以我认为答案是你无法在 C# 中获得此原生。
With reflection you can get the method. This returns a MethodInfo object, and with this object you cannot get the types which are used in the method. So I think the answer is that you cannot get this native in C#.
今天,您可以通过调用 LocalVariables 来自 MethodBody 类。
例如:
For today you can get the information by calling LocalVariables from the MethodBody class.
For example: