【.NET Core】你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟
你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟
文章目录
- 你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟
- 一、概述
- 二、CallerMemberNameAttribute类
- 三、CallerFilePathAttribute 类
- 四、CallerLineNumberAttribute 类
- 五、使用示例
- 六、使用场景
- 6.1/可用于日志的记录
- 6.2/CallerMemberName简化InotifyPropertyChange的实现

一、概述
CallerMemberName、CallerFilePath、CallerLineNumber特性
CallerMemberName:调用方法的名称。
CallerFilePath:调用方法的所有的类文件绝对地址。
CallerLineNumber:调用方法所在行号,可以用来记录日志,能够获取记录日志所在的行号和方法及调用文件。
二、CallerMemberNameAttribute类
允许获取方式调用方的方法或属性名称。
将CallerMemberName
属性应用于具有默认值的可选参数。必须为可选参数指定显示默认值。不能将此属性应用于未指定为可选参数。
可以使用CallerMemberName
特性来避免将成员名称指定为所调用的方法的String参数。通过使用这种技术,可以避免"重命名重构"不更改String值的问题。这对于以下任务特别有用:
- 使用跟踪和诊断例程
- 在绑定数据时实现
INotifyPropertyChanged
接口。此接口允许对象的属性通知绑定控件该属性已更改,以便此控件能够显示更新的信息。 如果没有CallerMemberName
特性,则必须将属性名称指定为文本。
三、CallerFilePathAttribute 类
允许获取包含调用方法的源文件的完整路径。这是编译时的文件路径。
将特性应用于CallerFilePath
具有默认值的可选参数。必须为可选参数指定显示默认值。不能将此属性应用于未指定为可选参数。
四、CallerLineNumberAttribute 类
允许获取源文件中调用方法的行号。
将 CallerLineNumber
属性应用于具有默认值的可选参数。 必须为可选参数指定显式默认值。 不能将此属性应用于未指定为可选参数。
五、使用示例
public void DoProcessing()
{TraceMessage("Something happened.");
}public void TraceMessage(string message,[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{System.Diagnostics.Trace.WriteLine("message: " + message);System.Diagnostics.Trace.WriteLine("member name: " + memberName);System.Diagnostics.Trace.WriteLine("source file path: " + sourceFilePath);System.Diagnostics.Trace.WriteLine("source line number: " + sourceLineNumber);
}
六、使用场景
6.1/可用于日志的记录
public class LogHelp
{public static void Info(string message,[CallerMemberName] string memberName = "",[CallerFilePath] string sourceFilePath = "",[CallerLineNumber] int sourceLineNumber = 0){Console.WriteLine("信息为: " + message);Console.WriteLine("方法名称: " + memberName);Console.WriteLine("源文件地址: " + sourceFilePath);Console.WriteLine("方法使用所在行号: " + sourceLineNumber);}public static void Debug(string message,[CallerMemberName] string memberName = "",[CallerFilePath] string sourceFilePath = "",[CallerLineNumber] int sourceLineNumber = 0){Console.WriteLine("信息为: " + message);Console.WriteLine("方法名称: " + memberName);Console.WriteLine("源文件地址: " + sourceFilePath);Console.WriteLine("方法使用所在行号: " + sourceLineNumber);}public static void Error(Exception ex,[CallerMemberName] string memberName = "",[CallerFilePath] string sourceFilePath = "",[CallerLineNumber] int sourceLineNumber = 0){Console.WriteLine("信息为: " + ex.Message);Console.WriteLine("方法名称: " + memberName);Console.WriteLine("源文件地址: " + sourceFilePath);Console.WriteLine("方法使用所在行号: " + sourceLineNumber);}}
6.2/CallerMemberName简化InotifyPropertyChange的实现
在WPF中,当我们要使用MVVM的方式绑定一个普通对象的属性时,界面上往往需要获取到属性变更的通知。一般我们会新建一个类,并继承InotifyPropertyChange接口。
class NotifyObject : INotifyPropertyChanged
{private int number;public int Number{get { return number; }set { number = value; OnPropertyChanged("Number"); }}private string text;public string Text{get { return text; }set { text = value; OnPropertyChanged("Text"); }}public event PropertyChangedEventHandler PropertyChanged;protected void OnPropertyChanged(string propertyName = ""){PropertyChangedEventHandler handler = PropertyChanged;if (handler != null){handler(this, new PropertyChangedEventArgs(propertyName));}}
}
这么做有一个比较大的隐患,那就是用了字符串的硬编码的方式传递了属性名称,一旦拼写错误或因为重构代码忘记去更新这个字符串时,这样就会导致界面上得不到更新。
硬编码的方式来保证两者的一致性是不靠谱的行为
可以是使用InotifyPropertyChange实现
class NotifyObject : INotifyPropertyChanged
{private int number;public int Number{get { return number; }set { number = value; OnPropertyChanged(); }}private string text;public string Text{get { return text; }set { text = value; OnPropertyChanged(); }}public event PropertyChangedEventHandler PropertyChanged;protected void OnPropertyChanged([CallerMemberName]string propertyName = ""){PropertyChangedEventHandler handler = PropertyChanged;if (handler != null){handler(this, new PropertyChangedEventArgs(propertyName));}}
}
在新的OnpertyChangeEventHandler,用[CallerMemberName]属性修饰参数,那么在某个属性发生改变时,会调用此函数,propertyName就有了该属性的名字,因此实现前面相同的功能,但我们不需要显示传入属性名了。
相关文章:

【.NET Core】你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟
你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟 文章目录 你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟一、概述二、CallerMemberNameAttribute类三、CallerFilePathAttribute 类四、CallerLineNumberAttribute 类…...
ubuntu删除opencv
要完全删除OpenCV 3.4.5版本,你可以按照以下步骤进行操作: 卸载OpenCV库: 首先,你需要卸载OpenCV 3.4.5版本。可以使用以下命令卸载OpenCV库: sudo apt-get purge libopencv*这将删除OpenCV库及其相关文件。 删除O…...

K8s源码分析(二)-K8s调度队列介绍
本文首发在个人博客上,欢迎来踩! 本次分析参考的K8s版本是 文章目录 调度队列简介调度队列源代码分析队列初始化QueuedPodInfo元素介绍ActiveQ源代码介绍UnschedulableQ源代码介绍**BackoffQ**源代码介绍队列弹出待调度的Pod队列增加新的待调度的Podpod调…...
OpenGL ES 面试高频知识点(二)
说说纹理常用的采样方式? 最邻近点采样(GL_NEAREST)和双线性采样(GL_LINEAR)。 GL_NEAREST 采样是 OpenGL 默认的纹理采样方式,OpenGL 会选择中心点最接近纹理坐标的那个像素,纹理放大的时候会有锯齿感或者颗粒感。 **GL_LINEAR 采样会基于纹理坐标附近的纹理像素,计…...

2024第十六届“中国电机工程学会杯”数学建模A题B题思路分析
文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间:2024…...
面向对象的三大特性:封装、继承、多态
一、封装 封装是面向对象的核心思想。是以类为载体,将对象的属性和行为封装起来,对外隐藏其实现细节。 封装保证了类内部数据结构的完整性,使得外部(使用该类的用户)不能轻易地直接操作此数据结构,只能执…...
目标检测YOLO实战应用案例100讲-基于深度学习的交通场景多尺度目标检测算法研究与应用(中)
目录 3.4 实验结果与分析 深度融合注意力跨尺度复合空洞残差交通目标检测算法...
前端GET请求下载后端返回数据流文件,并且处理window.open方法跳转白屏方法
平时常用导出都是用window.open方法 点击跳转连接:使用 window.open 下载 const downError 地址?&参数${参数|| }; const downError Url/xxx/xxx?&orgId${orgId || };window.open(downError, "_self");//调用window.open方法导出 而使用…...
SD321放大器3V输入电流电压保护二极管25C电源电流
Sd 321运算放大器可以在单电源或双电源电压下工作, 可以使用最坏情况下的非反相单位增益连接来适应。如 具有真微分输入,并且保持在线性模式,输入共模电压 果放大器必须驱动较大的负载电容,则应使用较大的闭 为0。Vpc-这种放大器可…...

geoserver SQL注入、Think PHP5 SQL注入、spring命令注入
文章目录 一、geoserver SQL注入CVE-2023-25157二、Think PHP5 SQL注入三、Spring Cloud Function SpEL表达式命令注入(CVE-2022-22963) 一、geoserver SQL注入CVE-2023-25157 介绍:GeoServer是一个开源的地理信息系统(GIS&#…...

scrapy的入门
今天我们先学习一下scrapy的入门,Scrapy是一个快速的高层次的网页爬取和网页抓取框架,用于爬取网站并从页面中提取结构化的数据。 1. scrapy的概念和流程 1.1 scrapy的概念 我们先来了解一下scrapy的概念,什么是scrapy: Scrapy是一个Python编写的开源网络爬虫框架…...

大数据Scala教程从入门到精通第七篇:Scala在IDEA中编写Hello World
一:Scala在IDEA中编写Hello World 想让我们的idea支持scala的编写,需要安装一个插件。...

设计模式之数据访问对象模式
在Java编程的浩瀚星海中,有一个模式低调却强大,它像是一位默默无闻的超级英雄,支撑起无数应用的数据脊梁——那就是数据访问对象(DAO, Data Access Object)模式!想象一下,如果你能像操纵魔法一样…...
Spring aop切面编程
Spring aop切面编程 如何使用利用AuditAction创建切入点 如何使用 Aspect // 1. 创建一个类,用Aspect注解标记它,表明这是一个切面类。 Component public class LoggingAspect {// 2. 定义切点:在通知方法上,使用切点表达式来指定…...

如何更好地使用Kafka? - 事先预防篇
要确保Kafka在使用过程中的稳定性,需要从kafka在业务中的使用周期进行依次保障。主要可以分为:事先预防(通过规范的使用、开发,预防问题产生)、运行时监控(保障集群稳定,出问题能及时发现&#…...
如何解决 IPA 打包过程中的 “Invalid Bundle Structure“ 错误
哈喽,大家好呀,淼淼又来和大家见面啦,咱们行业内的应该都知道,在开发 iOS 应用时,将应用打包成 IPA 文件是常见的步骤之一。最近很多小伙伴们说在打包过程中,有时会遇到 "Invalid Bundle Structure&qu…...
Vuex:Vue.js 的状态管理库
一、Vuex 简介 Vuex 是 Vue.js 的状态管理模式和库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 的出现解决了组件间共享状态的问题,使得状态管理变得简单、可预测和可维护。 二、Vuex 核心概…...

【简单介绍下Sass】
🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…...

IM 是什么?
在当今数字化的时代,即时通讯(IM)已经渗透到人们的日常生活和企业的工作环境中。IM技术的快速i发展为人们提供了一种高效、便捷的沟通方式,不仅推动了社会的信息化进程,也提升了企业的协同效率和竞争力。 作为企业级I…...

俄罗斯方块的代码实现
文章目录 首先是头文件的引入部分接下来是一些预处理指令接下来定义了两个结构体:接下来是全局变量g_hConsoleOutput,用于存储控制台输出句柄。之后是一系列函数的声明最后是main函数源码 首先是头文件的引入部分 包括stdio.h、string.h、stdlib.h、tim…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...