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

问题描述 投票:2回答:5

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

Console.cs具有程序Main类。

Business.cs具有三个类别,分别为CustomerOrderOrderline

无论如何,在C#中是否可以在运行时(也许通过反射)确定业务对象是否在名为Business.cs的文件中?

c# reflection types filenames .net-assembly
5个回答
1
投票

C#编译器不会将此信息发送到DLL中,因此无法通过反射获得。但是,从调试中您会知道,debugger可以将编译后的位置与源代码位置进行匹配。它通过PDB文件执行此操作。因此,从理论上讲,您可能会运送PDB文件,并调用非托管调试器或诊断符号存储API(请参阅MSDN中的常规参考>非托管API参考)来确定给定方法的定义位置。但是,您实际上不能为一个类执行此操作,因为可以使用部分类将一个类分散在多个文件中。


1
投票

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

但是,如果需要进行此操作,则出于除软件静态分析之类的其他目的,您可能走在错误的轨道上,应该考虑其他解决方案。

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

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

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

0
投票

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


0
投票

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


0
投票

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

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

根据您的方法。

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

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

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

  StackTrace st = new StackTrace(new StackFrame(1));
  st.GetFrame(1).GetFileName());
© www.soinside.com 2019 - 2024. All rights reserved.