在c#中查找已编译类的源文件

时间:2012-10-23 19:58:15

标签: c# .net reflection filesystems

我希望在一组编译的.net程序集中找到特定类的相关源文件。

e.g。

MyAsm.Namespace.Foo  -> C:\Source\foo.cs
MyAsm.Namespace.Bar  -> C:\Source\Code\MoreCode\Common.cs
MyAsm.Namespace2.Bar -> C:\Source\Code\MoreCode\Common.cs
...

我有使用标准System.Reflection功能的程序集反射/提取我感兴趣的类型信息。

我现在需要找到该类的原始.cs源文件。虽然我有一个蛮力解决方案作为一种解决方法,但它的速度令人无法接受。

我希望在5秒内完成整个过程。目前,反射提取部分花费不到1秒,“文件关联”需要几分钟。我不认为在4秒内扫描几个MB是不合理的。

不幸的是,有一些警告会阻止捷径。

  • 我不知道文件的名称,所以我需要每次运行dir / s *.cs,以枚举所有潜在的源文件。

  • 类名称并不总是与源文件匹配,它可以在可能的位置提示,但不能保证其工作。

  • 在某些情况下,同一文件中定义了多个类。

  • 有大约20k .cs文件/ 63MB的来源。

  • 我需要~10k类/文件之间的关联。

  • 我不想逐步构建一个带有文件名/类的DB,因为文件内容会发生变化,我将无法维护这个DB等(尽管我可能需要如果一切都失败了,沿着这条路走下去。)

  • 操作系统将继续运行,不会启用Windows搜索/索引,所以也没有任何欢乐。

我尝试了什么:

  • 使用findstr.exe - 太慢了

  • 创建.net应用,将所有文件加载到内存中。 - 太慢找到* .cs /加载所有 文件,一旦文件存入内存就快速扫描。

  • 从所有较小的文件创建一个大型源文件,加载它,扫描等 - 再次,太慢了。建立文件需要几分钟,加载后快速。

  • 读取PDB文件 - 我正在调查PDB2XML.exe,虽然它输出文件名并且运行速度很快,但我无法看到如何将类与文件名相关联。

那么,是否有人有其他建议,魔术或PDB2XML的一些经验?

4 个答案:

答案 0 :(得分:1)

如果文件在磁盘上,使用PDB是最好的选择IMHO。文件名(由ISymbolDocument.URL表示)与序列点相关。序列点与方法(包括属性获取/设置)有关,而不是类。当然,.NET类源可以存储在多个文件中。因此,您必须浏览所有类型的成员(例如使用反射)来确定所有相应的文件。

答案 1 :(得分:1)

这并不能完全解决您所面临的问题,因为您希望获得任意类的文件路径,但这对我的使用来说很容易,只是从源位置获取指向某个文件的指针。我在单元测试中使用它,因此性能不是很重要。

var x = new StackTrace(true);
var file = x.GetFrame(0).GetFileName();

答案 2 :(得分:0)

我不知道.NET中的文件名和程序集名称之间有任何关系,实际上可能在一个文件中定义了多个程序集,所以我看不到如何在没有物理查看的情况下执行此操作每个源代码文件,搜索类定义或维护运行索引。

答案 3 :(得分:0)

如果您能够编辑源。您可以使用反射和System.Runtime.CompilerServices.CallerFilePath做到这一点。只需将属性添加到每个文件的源中即可。您可能需要为部分类考虑一些聪明的方法。

此示例提供了放置属性的源文件和行号。

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
public sealed class SourceInfoAttribute : Attribute
{
    public SourceInfoAttribute([CallerLineNumber]int sourceLineNumber = 0, [CallerFilePath] string sourceFilePath = "")
    {
        SourceLineNumber = sourceLineNumber;
        SourceFilePath = sourceFilePath;
    }

    internal int SourceLineNumber { get; set; }
    internal string SourceFilePath { get; set; }
}