假设我有一个包含两个文件的应用程序。Console.cs
和Business.cs
Console.cs
具有程序Main
类。
Business.cs
具有三个类别,分别为Customer
,Order
和Orderline
。
无论如何,在C#中是否可以在运行时(也许通过反射)确定业务对象是否在名为Business.cs的文件中?
C#编译器不会将此信息发送到DLL中,因此无法通过反射获得。但是,从调试中您会知道,debugger可以将编译后的位置与源代码位置进行匹配。它通过PDB文件执行此操作。因此,从理论上讲,您可能会运送PDB文件,并调用非托管调试器或诊断符号存储API(请参阅MSDN中的常规参考>非托管API参考)来确定给定方法的定义位置。但是,您实际上不能为一个类执行此操作,因为可以使用部分类将一个类分散在多个文件中。
如果以调试模式进行编译,则可能可以使用Cecil(Mono项目的一部分)从调试符号中提取源文件名。但是,当您以发布模式进行编译时,此信息可能会丢失。
但是,如果需要进行此操作,则出于除软件静态分析之类的其他目的,您可能走在错误的轨道上,应该考虑其他解决方案。
如果将类放在Business名称空间中,则可以使用反射来查找对象是否来自该名称空间:
namespace Business {
class Customer {}
class Order {}
class OrderLine {}
}
var myObject = new Customer();
Console.WriteLine(myObject.GetType().Namespace); // writes "Business"
我相信最接近的是typeof(Customer).Assembly.Location
。但是,这只会给您DLL,而不是源代码的位置(这很有意义,因为源代码通常不会包含在二进制文件中)。
*。PDB(调试信息文件)文件应具有该信息。否则,我将无法获得它,因为代码文件只是编译代码不应该关心的抽象。
不确定您的用例是什么,但是如果有人打电话给您,您可以添加编译器指令
[CallerFilePath] string file = "", [CallerLineNumber] int LineNo = 0
根据您的方法。
如果不是访问此文件的最佳方法,是使用生成的.pdb文件。该格式已发布,并且提供了可用于访问文件的C ++ dll,但是,如果pdb文件中包含该文件,则读取文件(以及可能的行号)的最简单方法是使用stacktrace
您可以在异常中访问堆栈,因此,如果某个类允许您在不应该尝试的地方传递null引发异常,则可以尝试捕获它并获得堆栈跟踪。
如果您需要调用文件,但又不想添加编译器指令,因为有人可以简单地覆盖它,则可以执行以下操作:
StackTrace st = new StackTrace(new StackFrame(1));
st.GetFrame(1).GetFileName());