介绍
在csharp中,CallerMemberName
, CallerFilePath
, 和 CallerLineNumber
是编译时常量,它们是csharp 5.0引入的特性,用于提供有关调用堆栈的信息,通常用于日志记录和调试。这些特性可以自动填充方法的参数,无需显式传递信息。
所属命名空间:
System.Runtime.CompilerServices
所属程序集:
System.Runtime.dll
CallerMemberName
定义
CallerMemberNameAttribute 类
允许获取方法调用方的方法或属性名称。
[System.AttributeUsage(System.AttributeTargets.Parameter, Inherited=false)]
public sealed class CallerFilePathAttribute : Attribute
作用
CallerMemberName
提供调用方成员的名称(方法或属性)。
使用效果
使用示例
定义一个方法加上一个默认参数,增加CallerMemberName
特性
public void Work([CallerMemberName] string memberName = "")
{
Console.WriteLine("CallerMemberName:" + memberName);
}
在方法中调用:
void Playing()
{
Work();
}
在构造函数中调用:
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
TestClass testClass = new TestClass();
// testClass.Playing();
Console.ReadKey();
}
}
class TestClass
{
public TestClass()
{
Work();
}
public void Playing()
{
Work();
}
public void Work([CallerMemberName] string memberName = "")
{
Console.WriteLine("CallerMemberName:" + memberName);
}
}
CallerFilePath
定义
CallerFilePathAttribute 类
允许获取包含调用方的源文件的完整路径。 这是编译时的文件路径。
[System.AttributeUsage(System.AttributeTargets.Parameter, Inherited=false)]
public sealed class CallerFilePathAttribute : Attribute
作用
CallerFilePath
提供调用者的源文件路径。
使用示例:
定义一个方法加上一个默认参数,增加CallerFilePath
特性,调用时,会自动返回调用文件的完整路径
class TestClass
{
public void Playing()
{
Work();
}
public void Work([CallerFilePath] string filePath = "")
{
Console.WriteLine("CallerFilePath:" + filePath);
}
}
CallerLineNumber
定义
CallerLineNumberAttribute 类
允许获取源文件中调用方法的行号。
[System.AttributeUsage(System.AttributeTargets.Parameter, Inherited=false)]
public sealed class CallerLineNumberAttribute : Attribute
作用
CallerLineNumber
提供调用者的源文件中的行号。
使用场景
CallerMemberName
、 CallerFilePath
、CallerLineNumber
几个特性必须用于具有默认值的可选参数。 必须为可选参数指定显式默认值。 不能将特性用于未指定为可选的参数。
1.MVVM模式
在绑定数据时实现 INotifyPropertyChanged 接口。 此接口允许对象的属性通知绑定控件该属性已更改,以便此控件能够显示更新的信息。 如果没有 CallerMemberName
特性,则必须将属性名称指定为文本。
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
如果不加[CallerMemberName]
,每次调用OnPropertyChanged
时,都要加上对应属性
加了[CallerMemberName]
,只需要直接调用OnPropertyChanged();
无需再一一传参数。
public class MainWindowViewModel : ViewModelBase
{
private string _name;
private string _mySelectedItem;
private string _status;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}
public string MySelectedItem
{
get
{
return _mySelectedItem;
}
set
{
_mySelectedItem = value;
OnPropertyChanged();
}
}
public string Status
{
get
{
return _status;
}
set
{
_status = value;
OnPropertyChanged();
}
}
}
2.日志
在日志记录中包含调用该方法的信息,用于调试和调用记录,创建一个打印日志的方法,加上上面这些标签,然后只要在需要打印的地方调用,即可打印,使用时把`。
public void Log(
string message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0
)
{
//打印日志
Console.WriteLine("------------------------");
Console.WriteLine("Message:" + message);
Console.WriteLine("MemberName:" + memberName);
Console.WriteLine("FilePath:" + sourceFilePath);
Console.WriteLine("LineNumber:" + sourceLineNumber);
Console.WriteLine("------------------------");
}
完整代码示例:
internal class Program
{
static void Main(string[] args)
{
TestClass testClass = new TestClass();
testClass.Log("主函数执行开始");
Console.WriteLine("Hello, World!");
testClass.Playing();
testClass.Log("主函数执行结束");
Console.ReadKey();
}
}
class TestClass
{
public void Playing()
{
Log("执行play");
}
public void Log(
string message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0
)
{
//打印日志
Console.WriteLine("------------------------");
Console.WriteLine("Message:" + message);
Console.WriteLine("MemberName:" + memberName);
Console.WriteLine("FilePath:" + sourceFilePath);
Console.WriteLine("LineNumber:" + sourceLineNumber);
Console.WriteLine("------------------------");
}
}
效果: