Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在c中查找已编译类的源文件#_C#_.net_Reflection_Filesystems - Fatal编程技术网

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

C# 在c中查找已编译类的源文件#,c#,.net,reflection,filesystems,C#,.net,Reflection,Filesystems,我正在寻找一组编译的.net程序集中特定类的关联源文件 e、 g 我使用标准的System.reflection功能对程序集反射/提取类型信息感兴趣 现在我需要找到该类的原始.cs源文件。虽然我有一个蛮力解决方案作为解决方案,但它的速度慢得令人无法接受 我希望整个过程能在5秒内完成。目前,反射提取部分只需不到1秒的时间,“文件关联”只需几分钟。我不认为在4秒内扫描几MB是不合理的 不幸的是,有两个警告,防止捷径 我不知道文件的名称,所以每次运行时我都需要执行dir/s*.cs来枚举所有可能的源

我正在寻找一组编译的.net程序集中特定类的关联源文件

e、 g

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

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

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

不幸的是,有两个警告,防止捷径

  • 我不知道文件的名称,所以每次运行时我都需要执行
    dir/s*.cs
    来枚举所有可能的源文件

  • 类名并不总是与源文件匹配,它可以提示一个可能的位置,但不能保证工作正常

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

  • 每63MB源代码中约有20k.cs文件

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

  • 我不希望用声明的文件名/类增量地构建一个数据库,因为文件内容将发生变化,并且我将很难维护这个数据库等(尽管如果其他一切都失败了,我可能不得不走这条路)

  • 这将运行在操作系统上,不会启用windows搜索/索引,因此也没有乐趣

我所尝试的:

  • 使用findstr.exe-速度太慢

  • 创建.net应用程序,将所有文件加载到内存中。-太慢,无法找到*.cs/加载所有 文件,快速扫描文件,一旦它们在内存中

  • 从所有较小的文件中创建一个较大的源文件、加载、扫描等—同样,速度太慢。构建文件需要几分钟,加载后速度很快

  • 阅读PDB文件-我正在研究PDB2XML.exe,虽然它确实输出文件名,而且运行速度很快,但我看不出如何将类与文件名相关联


那么,有人对PDB2XML有其他建议、魔术或经验吗?

我不知道.NET中的文件名和程序集名之间有任何关系,事实上,一个文件中可能定义了多个程序集,因此如果不实际查看每个源代码文件并搜索类定义或维护一个运行索引,我看不出如何做到这一点。

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

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

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

如果您能够编辑源。您可以使用反射和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; }
}    

如果系统上不存在原始源文件,该怎么办?一个非常简单的方法是对类名进行文件搜索,比如查找所有包含
class\s+
@BenFinkel的文件。这是我唯一能做的事guarantee@MohamedNuur这是我的“我尝试过的”列表中的第二项,加载所有文件的时间太长了。这正是我想要的。但有一件事,它不是每个方法都返回
GetSequencePoints
的输出。从我所看到的自动属性。这是有意义的,因为调试器不会单步执行它们。有没有办法将它们关联起来?正如您所发现的,编译器不会为自动属性发出任何符号,因此如果类只包含这些符号,您将无法确定其源文件。但这应该是非常罕见的。我应该在问题中说这一点,但我需要在编译时解决,或者在编译后解决,而不是在运行时解决。西蒙的回答正是我所需要的。哦,不,我不认为这很好地解决了你的特定问题,但我把它放在这里,因为它不值得一个全新的问题,我想要分享信息。
[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; }
}