如何在运行时从已编译的应用程序中确定代码文件文件名

时间:2011-02-11 23:25:49

标签: c# reflection types filenames .net-assembly

假设我有一个包含两个文件的应用程序。 Console.csBusiness.cs

Console.csMain课程。

Business.cs有三个名为CustomerOrderOrderline的类。

C#中是否存在运行时(可能是反射)确定业务对象位于名为Business.cs的文件中?

5 个答案:

答案 0 :(得分:1)

如果在调试模式下编译,您可以使用Cecil(Mono项目的一部分)从调试符号中提取源文件名。但是当你在发布模式下编译时,这些信息可能会丢失。

但是,如果您需要来执行此操作,除了您的软件的静态分析之外的其他目的,您可能在错误的轨道上并且应该考虑另一种解决方案。

如果将类放在Business命名空间中,则可以使用反射来查找对象是否来自该命名空间:

namespace Business {
    class Customer {}
    class Order {}
    class OrderLine {}
}

var myObject = new Customer();
Console.WriteLine(myObject.GetType().Namespace); // writes "Business"

答案 1 :(得分:1)

C#编译器不会将此信息发送到DLL中,因此无法通过反射获得。但是,正如您在调试时所知,调试器可以将编译的位置与源代码位置相匹配。它通过PDB文件完成此操作。因此,您可能需要发布PDB文件,并调用非托管调试器或诊断符号存储API(请参阅MSDN中的常规参考>非托管API参考)以确定给定方法的定义位置。但是,你不能真正为一个类做这个,因为一个类可以使用部分类分布在多个文件中。

答案 2 :(得分:0)

我相信你最接近的是typeof(Customer).Assembly.Location。但是,这只会给你DLL,而不是源代码的位置(这是有意义的,因为源代码通常不会包含在二进制文件中)。

答案 3 :(得分:0)

*。PDB(调试信息文件)文件应具有该信息。否则我认为没办法得到它,因为代码文件只是编译代码不应该关心的抽象。

答案 4 :(得分:0)

不确定用例是什么,但是如果有人打电话给您,则可以添加 编译器指令

[CallerFilePath] string file = "", [CallerLineNumber]    int LineNo = 0 

采用您的方法。

如果不是最好的访问方式,则是使用生成的.pdb文件。该格式已发布,并且提供了可用于访问文件的C ++ dll,但是,如果pdb文件中包含该文件,则读取文件(以及可能的行号)的最简单方法是使用stacktrace

您可以在异常中访问堆栈,因此,如果某个类允许您在不应该尝试传递null的地方传递null引发异常,则可以尝试捕获它并获得堆栈跟踪。

如果您需要调用文件,但又不想添加编译器指令,因为有人可以简单地覆盖它,则可以执行以下操作:

  StackTrace st = new StackTrace(new StackFrame(1));
  st.GetFrame(1).GetFileName());