C#类知道实例化它的文件是什么吗?
有没有可能告诉你什么文件在C#中实例化了一个类 例如,如果我有Page1.cs和Page2.cs,myclass.cs中的构造函数是否可以知道哪个页面从中创建了对象?您可以通过“”属性执行此操作。本质上,您可以在类的构造函数上创建一些额外的可选参数,对它们应用一些特殊属性,编译器将自动为您填写详细信息。例如:C#类知道实例化它的文件是什么吗?,c#,C#,有没有可能告诉你什么文件在C#中实例化了一个类 例如,如果我有Page1.cs和Page2.cs,myclass.cs中的构造函数是否可以知道哪个页面从中创建了对象?您可以通过“”属性执行此操作。本质上,您可以在类的构造函数上创建一些额外的可选参数,对它们应用一些特殊属性,编译器将自动为您填写详细信息。例如: using System.Runtime.CompilerServices; public MyClass { public MyClass( [CallerMemb
using System.Runtime.CompilerServices;
public MyClass
{
public MyClass(
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
...
}
}
您只需将其称为:
var instance = new MyClass();
编译器将自动填写调用者的成员名称、文件路径和行号。您可以通过“”属性完成此操作。本质上,您可以在类的构造函数上创建一些额外的可选参数,对它们应用一些特殊属性,编译器将自动为您填写详细信息。例如:
using System.Runtime.CompilerServices;
public MyClass
{
public MyClass(
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
...
}
}
您只需将其称为:
var instance = new MyClass();
编译器将自动填写调用者的成员名称、文件路径和行号。解决方案1(需要.NET 4.5并编辑代码)
假设这是Caller.cs
public class Caller
{
public Caller()
{
new Callee();
}
}
这是Callee(将被调用的类):
输出将是
c:\users\francesco\source\repos\ConsoleApp19\ConsoleApp19\Caller.cs
较长的解释如下:[CallerFilePath]
将负责检索调用方文件名,并将其存储在被调用方的构造函数的callerFileName
参数中。
这需要编辑您的源代码和至少.NET 4.5,我不确定每个应用程序都会满足这一要求
解决方案2(只需编辑代码即可)
因此,您只需更改被调用方的构造函数
,向其传递一个字符串参数,该参数将是调用方的名称(例如“Caller.cs”
):
如果您只有几个类(Caller
是其中的一个),并且可以使用.NET framework的每个版本,那么这当然是一个可行的解决方案
无论如何,不建议使用一个文件来承载多个类,但它可能是由其他人在遗留代码中完成的:因此您可以获取文件名,但仍然不能获取调用类,这就是为什么您可以使用我刚才列出的方法(直接将调用方的名称传递给构造函数)而不是第一个方法
解决方案3(不需要代码编辑)
最后但并非最不重要的一点是,如果您只是从Visual Studio进行调试,则不必执行上述任何操作:只需使用StackFrame:为被调用方的构造函数设置断点,然后单击StackFrame下拉列表:
这将不需要任何代码编辑,并且清楚地表明被调用方
的构造函数是由调用方
调用的;您只需单击菜单中的任意一行,即可进入呼叫线路。解决方案1(需要.NET 4.5并编辑您的代码)
假设这是Caller.cs
public class Caller
{
public Caller()
{
new Callee();
}
}
这是Callee(将被调用的类):
输出将是
c:\users\francesco\source\repos\ConsoleApp19\ConsoleApp19\Caller.cs
较长的解释如下:[CallerFilePath]
将负责检索调用方文件名,并将其存储在被调用方的构造函数的callerFileName
参数中。
这需要编辑您的源代码和至少.NET 4.5,我不确定每个应用程序都会满足这一要求
解决方案2(只需编辑代码即可)
因此,您只需更改被调用方的构造函数
,向其传递一个字符串参数,该参数将是调用方的名称(例如“Caller.cs”
):
如果您只有几个类(Caller
是其中的一个),并且可以使用.NET framework的每个版本,那么这当然是一个可行的解决方案
无论如何,不建议使用一个文件来承载多个类,但它可能是由其他人在遗留代码中完成的:因此您可以获取文件名,但仍然不能获取调用类,这就是为什么您可以使用我刚才列出的方法(直接将调用方的名称传递给构造函数)而不是第一个方法
解决方案3(不需要代码编辑)
最后但并非最不重要的一点是,如果您只是从Visual Studio进行调试,则不必执行上述任何操作:只需使用StackFrame:为被调用方的构造函数设置断点,然后单击StackFrame下拉列表:
这将不需要任何代码编辑,并且清楚地表明被调用方
的构造函数是由调用方
调用的;您只需单击菜单的任何一行,就可以进入调用行。一个类可以通过在构建过程中检查堆栈跟踪来了解实例化它的类。例如,如果要将其添加到类的构造函数中:
var creator = new StackTrace().GetFrame(1).GetMethod().DeclaringType.FullName;
…您将了解名为new
的代码的位置。类名称中的位置。当然,您可以检查声明类型的属性以了解程序集名称、位置等
请记住,如果使用链式构造函数,则必须将堆栈框架走得更远一点。此外,这对通过反序列化创建的任何对象都不起作用。类可以通过在构造期间检查堆栈跟踪来了解实例化它的类。例如,如果要将其添加到类的构造函数中:
var creator = new StackTrace().GetFrame(1).GetMethod().DeclaringType.FullName;
…您将了解名为new
的代码的位置。类名称中的位置。当然,您可以检查声明类型的属性以了解程序集名称、位置等
请记住,如果使用链式构造函数,则必须将堆栈框架走得更远一点。此外,这对通过反序列化创建的任何对象都不起作用。如果您只想将form1传递给form2,那么表单知道并拥有调用方的实例。cs是代码文件。Th