C#类知道实例化它的文件是什么吗?

C#类知道实例化它的文件是什么吗?,c#,C#,有没有可能告诉你什么文件在C#中实例化了一个类 例如,如果我有Page1.cs和Page2.cs,myclass.cs中的构造函数是否可以知道哪个页面从中创建了对象?您可以通过“”属性执行此操作。本质上,您可以在类的构造函数上创建一些额外的可选参数,对它们应用一些特殊属性,编译器将自动为您填写详细信息。例如: using System.Runtime.CompilerServices; public MyClass { public MyClass( [CallerMemb

有没有可能告诉你什么文件在C#中实例化了一个类

例如,如果我有Page1.cs和Page2.cs,myclass.cs中的构造函数是否可以知道哪个页面从中创建了对象?

您可以通过“”属性执行此操作。本质上,您可以在类的构造函数上创建一些额外的可选参数,对它们应用一些特殊属性,编译器将自动为您填写详细信息。例如:

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