.net 程序集的静态分析

发布于 2024-08-09 17:24:28 字数 269 浏览 11 评论 0原文

我有一个 C# 项目,我需要找到所有未从任何其他公共方法直接或间接调用的私有方法。

此外,对于从公共方法调用的每个私有方法,我需要知道它是哪个公共方法。然后我将确定该方法是否确实是从类的客户端调用的,如果不是,我将能够删除它。

过去,我使用了来自 Lutz Rorder 的代码,它是 Reflector 的基础 - 它有一个分析 IL 代码的选项,并在其之上提供对象模型。我现在找不到这个代码。

有什么建议吗? 也许指向 Lutz Rorder 代码?

萨尔

I have a C# project for which I need to find the all private methods which are not called from any other public method directly or indirectly.

In addition, for each private method which is called from a public method, I need to know which public method it is. Then I will detemine if that method is really called from a client of the class and if not I will be able to remove it.

In the past I used a code from Lutz Rorder which is the base of Reflector - it had an option to analyze IL code and gave object model on top of it. I cannot find this code now.

Any suggestion?
Maybe a point to that Lutz Rorder code?

Saar

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

2024-08-16 17:24:28

您应该查看 Nitriq Static Code Analysis for .Net - 他们有免费的社区版,其完整的许可证是相当合理。

You should check out Nitriq Static Code Analysis for .Net - They have a free community edition and their full blown license is pretty reasonable.

假装爱人 2024-08-16 17:24:28

正如 Thomas 所指出的,该工具 NDepend 可以帮助您在 .NET 代码库中查找未使用的代码。 免责声明:我是该工具的开发人员之一。

NDepend 建议编写 基于 LINQ 查询的代码规则 (CQLinq)。提议了大约200 个默认代码规则,其中 3 个专门用于未使用/dead code 检测:

NDepend 集成在 Visual Studio 中,因此可以检查/浏览/编辑这些规则就在 IDE 内。该工具还可以集成到您的 CI 流程中,并且可以构建报告,显示违反的规则和罪魁祸首代码元素。

如果您点击上面的这 3 个链接查看这些规则的源代码,您会发现涉及类型和方法的内容有点复杂。这是因为它们不仅检测未使用的类型和方法,而且还检测仅由未使用的死类型和方法(递归)使用的类型和方法。

这是静态分析,因此规则名称中的潜在前缀。如果代码元素通过反射使用,这些规则可能会将其视为未使用,但情况并非如此。

除了使用这 3 条规则之外,我还建议通过测试来衡量代码覆盖率并努力实现完全覆盖。通常,您会看到测试无法覆盖的代码实际上是可以安全丢弃的未使用/死代码。这在不清楚代码分支是否可达的复杂算法中特别有用。


此外,对于从公共方法调用的每个私有方法,我需要知道它是哪个公共方法。

要获取此信息,使用 CQLinq 您只需编写:

from m in Application.Methods
where m.IsPrivate
let publicMethodsCallingMe = m.MethodsCallingMe.Where(m1 => m1.IsPublic)
where publicMethodsCallingMe.Count() > 0
select new { m, publicMethodsCallingMe }

查询结果将很容易浏览:

浏览 CQLinq 查询结果

As pointed Thomas the tool NDepend can help you to find unused code in a .NET code base. Disclaimer: I am one of the developer of this tool.

NDepend proposes to write Code Rule over LINQ Query (CQLinq). Around 200 default code rules are proposed, 3 of them being dedicated to unused/dead code detection:

NDepend is integrated in Visual Studio, thus these rules can be checked/browsed/edited right inside the IDE. The tool can also be integrated into your CI process and it can build reports that will show rules violated and culprit code elements.

If you click these 3 links above toward the source code of these rules, you'll see that the ones concerning types and methods are a bit complex. This is because they detect not only unused types and methods, but also types and methods used only by unused dead types and methods (recursive).

This is static analysis, hence the prefix Potentially in the rule names. If a code element is used only through reflection, these rules might consider it as unused which is not the case.

In addition to using these 3 rules, I'd advise measuring code coverage by tests and striving for having full coverage. Often, you'll see that code that cannot be covered by tests, is actually unused/dead code that can be safely discarded. This is especially useful in complex algorithms where it is not clear if a branch of code is reachable or not.


In addition, for each private method which is called from a public method, I need to know which public method it is.

To obtain this information, with CQLinq you just need to write:

from m in Application.Methods
where m.IsPrivate
let publicMethodsCallingMe = m.MethodsCallingMe.Where(m1 => m1.IsPublic)
where publicMethodsCallingMe.Count() > 0
select new { m, publicMethodsCallingMe }

The query result will be easily browsable:

Browsing CQLinq query result

同展鸳鸯锦 2024-08-16 17:24:28

好吧,执行此操作的唯一方法(至少是我所知道的唯一方法......)意味着使用商业(但不是那么昂贵)工具,即 NDepend.

除此之外,您还可以针对已编译的程序集编写类似 SQL 的查询,从而实现非常细粒度的分析。他们称之为 CQL,语法是不言自明的,NDepend 的 IntelliSense/自动完成支持以及一般帮助/文档都非常好。

(据我所知,他们还提供功能齐全的试用版,如果这对您有帮助......)

HTH!

Well, the only method to do this (at least the only one that I know...) implies the use of a commercial (but not so expensive) tool, namely NDepend.

Among many other things, you can write SQL-like queries against your compiled assemblies, which allows for very fine-grained analysis. They call it CQL, the syntax is self-explaining, and NDepend's IntelliSense/auto-completion support as well as the general help/documentation are quite good.

(AFAIK they also provide a fully-featured trial, if that helps you...)

HTH!

蓝戈者 2024-08-16 17:24:28

不确定它是否能满足所有这些需求,但 FXCop 将为您完成其中大部分任务,并且还将帮助制定大量编码标准。无论哪种方式,都值得运行您的 C# 代码。

FXCop (MSDN)

Not sure if it will fulfil all these needs, but FXCop will do most of these for you and will help do a whole lot of coding standards as well. It's worth running over your c# code either way.

FXCop (MSDN)

贱人配狗天长地久 2024-08-16 17:24:28

Reflector仍然有这个功能。只需右键单击该方法,然后单击“分析”。单击树视图中的链接。

您没有说是否需要用代码来完成,或者只是“视觉上”。

如果需要代码,我相信您可以使用 Reflector SDK。

Reflector still has this functionality. Just right click the method, and click Analyze. Follow the links in the tree view.

You do not say whether you need to do it in code, or just 'visually'.

If needed for code, I am sure you can use the Reflector SDK.

淡淡の花香 2024-08-16 17:24:28

我也许可以使用 PowerCommands for Reflector 插件中的查询编辑器来帮助您解决此问题 (http://powercommands.codeplex .com)...我今晚会看看我能想出什么,然后明天告诉你。

否则,您也可以使用 CCI 或 Cecil 编写一个快速应用程序来完成此任务。

询问:

from a in AssemblyManager.Assemblies.Cast<IAssembly>()
where a.Name != "mscorlib" 
    && !a.Name.Contains("System")
from m in a.Modules.Cast<IModule>()
from t in m.Types.Cast<ITypeDeclaration>()
from mt in t.Methods.Cast<IMethodDeclaration>()
where mt.Visibility == MethodVisibility.Public 
    && !mt.RuntimeSpecialName 
    && !mt.SpecialName 
    && mt.Body is IMethodBody
from i in ((IMethodBody)mt.Body).Instructions.Cast<IInstruction>()
where i != null 
    && i.Value != null 
    && i.Value is IMethodReference 
    && ((IMethodReference)i.Value).Resolve() != null
    && ((IMethodReference)i.Value).Resolve().Visibility == MethodVisibility.Private
select new { 
    CallingMethod=t.Namespace + "." + t.Name + "." + mt.Name, 
    PrivateReferencedMethod=((ITypeReference)((IMemberReference)((IMethodReference)i.Value).Resolve()).DeclaringType).Namespace + "."
        + ((ITypeReference)((IMemberReference)((IMethodReference)i.Value).Resolve()).DeclaringType).Name + "."
        + ((IMethodReference)i.Value).ToString()
}

I might be able to help you with this one using the Query Editor in the PowerCommands for Reflector addin (http://powercommands.codeplex.com) ... I'll see what I can come up with tonight, then let you know tomorrow.

Otherwise you could also write a quick application using the CCI or Cecil that would do it.

Query:

from a in AssemblyManager.Assemblies.Cast<IAssembly>()
where a.Name != "mscorlib" 
    && !a.Name.Contains("System")
from m in a.Modules.Cast<IModule>()
from t in m.Types.Cast<ITypeDeclaration>()
from mt in t.Methods.Cast<IMethodDeclaration>()
where mt.Visibility == MethodVisibility.Public 
    && !mt.RuntimeSpecialName 
    && !mt.SpecialName 
    && mt.Body is IMethodBody
from i in ((IMethodBody)mt.Body).Instructions.Cast<IInstruction>()
where i != null 
    && i.Value != null 
    && i.Value is IMethodReference 
    && ((IMethodReference)i.Value).Resolve() != null
    && ((IMethodReference)i.Value).Resolve().Visibility == MethodVisibility.Private
select new { 
    CallingMethod=t.Namespace + "." + t.Name + "." + mt.Name, 
    PrivateReferencedMethod=((ITypeReference)((IMemberReference)((IMethodReference)i.Value).Resolve()).DeclaringType).Namespace + "."
        + ((ITypeReference)((IMemberReference)((IMethodReference)i.Value).Resolve()).DeclaringType).Name + "."
        + ((IMethodReference)i.Value).ToString()
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文