如何在运行时确定已编译应用程序的代码文件文件名
假设我有一个包含两个文件的应用程序。 Console.cs
和 Business.cs
Console.cs
具有程序 Main
类。
Business.cs
具有三个名为 Customer
、Order
和 Orderline
的类。
无论如何,C# 中是否可以在运行时(可能通过反射)确定业务对象位于名为 Business.cs 的文件中?
Let's say I have an application with two files.Console.cs
and Business.cs
Console.cs
has program Main
class.
Business.cs
has three classes named Customer
, Order
and Orderline
.
Is there anyway in C# to determine at runtime (maybe with reflection) that the business objects are in a file named Business.cs?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
C# 编译器不会将此信息发送到 DLL 中,因此无法通过反射获得它。但是,正如您从调试中了解到的那样,调试器可以将编译位置与源代码位置进行匹配。它通过 PDB 文件来完成此操作。因此,理论上您可以传送 PDB 文件,并调用非托管调试器或诊断符号存储 API(请参阅 MSDN 中的一般参考 > 非托管 API 参考)来确定给定方法的定义位置。但是,您实际上无法对类执行此操作,因为一个类可以使用部分类分布在多个文件中。
The C# compiler does not emit this information into the DLL, so it's not available through reflection. However, as you'll be aware from debugging, the debugger can match up compiled locations to source code locations. It does this through PDB files. So it might be theoertically possible for you to ship your PDB files, and invoke the unmanaged debugger or diagnostic symbol store API (see General Reference > Unmanaged API Reference in MSDN) to determine where a given method was defined. You can't really do this for a class, though, because a class could be spread across multiple files using partial classes.
如果您在调试模式下编译,您可能可以使用 Cecil (Mono 项目的一部分)来提取源文件名从调试符号。但是当您在发布模式下编译时,这些信息可能会丢失。
但是,如果您需要这样做,除了软件静态分析之外的其他目的,那么您可能走错了路,应该考虑其他解决方案。
如果将类放入 Business 命名空间中,则可以使用反射来查找对象是否来自该命名空间:
If you compile in debug mode you can probably use Cecil (part of Mono project) to extract the source filenames from the debug symbols. But when you compile in release mode this information probably gets lost.
However, if you need to do this, for other purposes than for example static analysis of your software, you are probably on the wrong track and should think of another solution.
If you put the classes in a Business namespace you could use reflection to find if an object comes from that namespace:
我相信您会得到的最接近的是
typeof(Customer).Assembly.Location
。但是,这只会为您提供 DLL,而不是源代码的位置(这是有道理的,因为源代码通常不会包含在二进制文件中)。I believe the closest you'll get is
typeof(Customer).Assembly.Location
. However, this will only give you the DLL, not the location of the source code (which makes sense, since the source code would normally not be included with the binaries).*.PDB(调试信息文件)文件应该包含该信息。否则我看不出有什么办法得到它,因为代码文件只是编译代码不应该关心的抽象。
*.PDB (debug info files) files should have that information. Otherwise I see no way to get it, since code files is just an abstraction which compiled code should not care about.
不确定您的用例是什么,但是如果有人打电话给您,那么您可以添加
您的方法中的编译器指令
。
如果不是,那么访问它的最佳方法是使用生成的 .pdb 文件。该格式已发布,并且可以使用 C++ dll 来访问该文件,但是如果包含在 pdb 文件中,读取该文件(以及可能的行号)的最简单方法是使用 stacktrace
您可以在异常中访问堆栈,因此,如果一个类允许您通过传递 null 来抛出异常,而您不应该尝试捕获它,那么您就会获得堆栈跟踪。
如果您需要调用文件但不想添加编译器指令,因为某些编译器指令可以简单地覆盖它,您可以执行以下操作:
not sure what your use case is, however if some one is calling you then you can add
compiler directives
in your method.
if not than your best way of accessing this is by using the .pdb file that get's generated. The format is published and a C++ dll is available that can be used to access the file however the easiest way to read the file (and possible line number) if included in the pdb file is using stacktrace
You can access the stack in an exception, so if a class allows you to throw an exception by passing null where you should not than try catch it and you have your stack trace.
if you need the calling file but do not want to add the compiler directives as some one can simply overwrite it you can do something like:
假设:
这意味着,通过在“NameSpaceGloballyVisibleByAllProjects”中添加此类:
您可以像这样简单地使用它:
注意:正如您所注意到的,有多个文件!这是因为 C# 中的“partial”关键字。因此,是否使用“files.Single()”取决于您...
我们现在只需在所有类型之上添加此属性即可
我们可以在 Visual Studio 中使用 Ctr-H(查找和替换)来完成此操作。
(不带双引号,但最后带有 ' '!)
(没有双引号,但最后有' '!)
Assuming :
It means that, by adding this class in "NameSpaceGloballyVisibleByAllProjects":
You can simply use it like this:
Note: As you notice there are more than one file! This is because of "partial" keyword in C#. So it's up to you to use "files.Single()" or not...
We just need to add this attribute above all types now
We can do that in Visual Studio with Ctr-H (Find-and-Replace).
(without double quotes, but with the final ' '!)
(without double quotes, but with the final ' '!)
现在可以通过
[CallerFilePathAttribute]
获得此功能。它允许您编写透明的调试函数,例如:它将输出如下消息:
This is now available via
[CallerFilePathAttribute]
. It allows you to write a transparent debugging function like:Which will output messages like: