使用 Mono.Cecil 列出所有调用方法的引用
List all references calling a method using Mono.Cecil
我正在开展一个清理遗留代码的项目,需要以编程方式查找在 .NET 4.5 服务引用(即 Reference.cs 文件)中调用某些 SOAP Web 方法的所有引用,以便我可以输出到文本文件或 Excel(基本上,引用与 CodeLens 功能一起列出)。我想我会使用 Mono.Cecil 库来完成这项任务。
我有指定程序集的方法,类 工作得很好,因为我可以打印所有方法的列表以供审查。但是关于如何获取特定方法的参考列表有什么想法吗?
// assemblyName is the file path for the specific dll
public static void GetReferencesList(string assemblyName)
{
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyName);
foreach (ModuleDefinition module in assembly.Modules)
{
foreach (TypeDefinition type in module.Types)
{
if (type.Name.ToLowerInvariant() == "classname")
{
foreach (MethodDefinition method in type.Methods)
{
if (method.Name.Substring(0, 4) != "get_" &&
method.Name.Substring(0, 4) != "set_" &&
method.Name != ".ctor" &&
method.Name != ".cctor" &&
!method.Name.Contains("Async"))
{
//Method name prints great here
Console.WriteLine(method.Name);
// Would like to collect the list of referencing calls here
// for later output to text files or Excel
}
}
}
}
}
}
}
我是这样做的:
static HashSet<string> BuildDependency(AssemblyDefinition ass, MethodReference method)
{
var types = ass.Modules.SelectMany(m => m.GetTypes()).ToArray();
var r = new HashSet<string>();
DrillDownDependency(types, method,0,r);
return r;
}
static void DrillDownDependency(TypeDefinition[] allTypes, MethodReference method, int depth, HashSet<string> result)
{
foreach (var type in allTypes)
{
foreach (var m in type.Methods)
{
if (m.HasBody &&
m.Body.Instructions.Any(il =>
{
if (il.OpCode == Mono.Cecil.Cil.OpCodes.Call)
{
var mRef = il.Operand as MethodReference;
if (mRef != null && string.Equals(mRef.FullName,method.FullName,StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
return false;
}))
{
result.Add(new string('\t', depth) + m.FullName);
DrillDownDependency(allTypes,m,++depth, result);
}
}
}
}
我正在开展一个清理遗留代码的项目,需要以编程方式查找在 .NET 4.5 服务引用(即 Reference.cs 文件)中调用某些 SOAP Web 方法的所有引用,以便我可以输出到文本文件或 Excel(基本上,引用与 CodeLens 功能一起列出)。我想我会使用 Mono.Cecil 库来完成这项任务。
我有指定程序集的方法,类 工作得很好,因为我可以打印所有方法的列表以供审查。但是关于如何获取特定方法的参考列表有什么想法吗?
// assemblyName is the file path for the specific dll
public static void GetReferencesList(string assemblyName)
{
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyName);
foreach (ModuleDefinition module in assembly.Modules)
{
foreach (TypeDefinition type in module.Types)
{
if (type.Name.ToLowerInvariant() == "classname")
{
foreach (MethodDefinition method in type.Methods)
{
if (method.Name.Substring(0, 4) != "get_" &&
method.Name.Substring(0, 4) != "set_" &&
method.Name != ".ctor" &&
method.Name != ".cctor" &&
!method.Name.Contains("Async"))
{
//Method name prints great here
Console.WriteLine(method.Name);
// Would like to collect the list of referencing calls here
// for later output to text files or Excel
}
}
}
}
}
}
}
我是这样做的:
static HashSet<string> BuildDependency(AssemblyDefinition ass, MethodReference method)
{
var types = ass.Modules.SelectMany(m => m.GetTypes()).ToArray();
var r = new HashSet<string>();
DrillDownDependency(types, method,0,r);
return r;
}
static void DrillDownDependency(TypeDefinition[] allTypes, MethodReference method, int depth, HashSet<string> result)
{
foreach (var type in allTypes)
{
foreach (var m in type.Methods)
{
if (m.HasBody &&
m.Body.Instructions.Any(il =>
{
if (il.OpCode == Mono.Cecil.Cil.OpCodes.Call)
{
var mRef = il.Operand as MethodReference;
if (mRef != null && string.Equals(mRef.FullName,method.FullName,StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
return false;
}))
{
result.Add(new string('\t', depth) + m.FullName);
DrillDownDependency(allTypes,m,++depth, result);
}
}
}
}