应该有一种工具,它已经以树形格式做这件事,但没有任何通常的嫌疑人似乎没有Find Usages舞蹈。
所以,这里试图通过查找所有成员变量来使用Reflection API,然后检查方法并确定它们是否触及它们。
你现在基本上是在查看IL,所以除非你想自己确定解析规则,否则你会想使用像塞西尔这样的反汇编程序。我正在使用deprecated single file implementation cause it's easy。像Roslyn分析器或JustDecompile插件就像另一条路线,但我没有经验。
肯定会出现边缘情况,如果你正在寻找一个完整的依赖关系图,代码将变得更加复杂 - 但对于快速和脏的分析,它至少应该给你一个概述。
所以,基本上你使用反射加上IL读者作出从变量地图 - >方法(你可以去太多的其他方式,但是这可能不值钱):
var variables = typeof(SmallBallOfMud).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
var methods = typeof(SmallBallOfMud).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic);
var d = new Dictionary<string, List<string>>();
foreach (var v in variables) d.Add(v.Name, new List<string>());
// this particular disassembler chokes on externally implemented methods
foreach (var m in methods.Where(m => (m.MethodImplementationFlags | MethodImplAttributes.IL) == 0)) {
var instructions = MethodBodyReader.GetInstructions(m);
foreach (var i in instructions) {
// we'll only check for direct field access here
var f = i.Operand as FieldInfo;
if (f == null) continue;
d[f.Name].Add(m.Name);
}
}
我们的结果将是如:
state1: Method1 (1), Method2 (1)
state2: Method2 (2)
state3: Method1 (1), Method2 (2)
这被读作“状态3”被“方法1”使用一次,“方法2”使用两次。
会不会只是成员变量?除非你也关心突变参数? –
R#可能会对您有所帮助。不知道是否有内置功能。 @MarkBrackett,OP正在讨论不需要成员变量的成员变量,因为它们只用于一种方法。 – bzlm
@bzlm,差不多。它们是全局变量,用于在全球范围内通过几十个函数中的状态。所以我试图将变量本地化到需要的每个函数中,并使用参数,以便程序及其数据的状态更容易理解,以便干净地封装并取消所有全局变量。 – eidylon