C#特性和反射
1。特性概念理解?
特性(Attribute)是用于在【运行时】传递程序中各种元素(比如类、属性、方法、结构、枚举、组件等)行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
特性是【运行时】给各种元素添加【声明性标签】。语法:[某个特性]。 声明性标签:官方称为元数据,即:metadata
元数据:保存在程序集中有关程序及其类型的数据。元数据主要用来描述C#中各种对象(类,方法,构造函数,属性等)。
// 特性主要用来给各种对象添加元数据。反射主要用来拿各种对象的元数据。
特性(Attribute)用于给对象添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.
Net 框架提供了两种主要特性:预定义特性和自定义特性。
问:属性和特性啥关系?没关系。两个概念。属性Property,是类的成员。特性Attribute,用来描述类,方法等对象的元数据。
常用的特性:
AttributeUsage,Conditional,Obsolete,Category,Description,Browsable,DefaultValue,Serializable,在学习自定义控件时会用到部分特性。
// 多个特性无顺序,多个中括号设置
// Description特性用来给属性添加描述信息(注释,解释)
// Category特性用来给属性分类,默认分类放到“杂项”
// Browsable特性用来控制属性能否在属性窗口中出现
三种预定义特性分类:
• AttributeUsage预定义特性
主要让开发者在自定义特性时,控制自定义特性的应用范围,掌握
预定义特性 AttributeUsage 描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。
规定该特性的语法如下:
[AttributeUsage(validon,AllowMultiple=allowmultiple,Inherited=inherited
)]
其中:
参数 validon 规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
参数 allowmultiple(可选的)为该特性的 AllowMultiple 属性(property)提供一个布尔值。如果为 true,则该特性是多用的。默认值是 false(单用的)。
参数 inherited(可选的)为该特性的 Inherited 属性(property)提供一个布尔值。如果为 true,则该特性可被派生类继承。默认值是 false(不被继承)。
例如:
// AttributeUsage特性,控制定义的特性在哪些对象上使用。
//即:自定义的特性MyAttribute可以应用到哪些目标上。Usage使用
// 平时自定义的特性最想用到:类上,方法,属性。
// AttributeTargets特性应用的目标。Targets目标
// AllowMultiple = true控制特性是否能在同一个元素上应用多次,
//false只能应用一次,是默认情况,true可能应用多次
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
• Conditional带条件特性
(了解,涉及到预定义指令)
这个预定义特性标记了一个条件方法,其执行依赖于指定的预处理标识符。
它会引起方法调用的条件编译,取决于指定的值,比如 Debug 或 Trace。例如,当调试代码时显示变量的值。
规定该特性的语法如下:
[Conditional(conditionalSymbol
)]
例如:[Conditional("DEBUG")]
下面的实例演示了该特性:
实例
#define DEBUG
using System;
using System.Diagnostics;
public class Myclass
{[Conditional("DEBUG")]public static void Message(string msg){Console.WriteLine(msg);}
}
class Test
{static void function1(){Myclass.Message("In Function 1.");function2();}static void function2(){Myclass.Message("In Function 2.");}public static void Main(){Myclass.Message("In Main function.");function1();Console.ReadKey();}
}
当上面的代码被编译和执行时,它会产生下列结果:
In Main function.
In Function 1.
In Function 2.
• Obsolete废弃特性
掌握
这个预定义特性标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为 obsolete(过时的)。
规定该特性的语法如下:
[Obsolete(message
)]
[Obsolete(message,iserror
)]
其中:
参数 message,是一个字符串,描述项目为什么过时以及该替代使用什么。
参数 iserror,是一个布尔值。如果该值为 true,编译器应把该项目的使用当作一个错误。默认值是 false(编译器生成一个警告)。
下面的实例演示了该特性:
实例
using System;
public class MyClass
{[Obsolete("Don't use OldMethod, use NewMethod instead", true)]static void OldMethod(){Console.WriteLine("It is the old method");}static void NewMethod(){Console.WriteLine("It is the new method");}public static void Main(){OldMethod();}
}
当您尝试编译该程序时,编译器会给出一个错误消息说明:
Don't use OldMethod, use NewMethod instead
如何自定义一个特性?
1。命名建议以Attribute结尾,建议使用大驼峰。
2。必须继承基类Attribute
3。使用AttributeUsage特性来控制自定义的特性的应用范围。
观察:怎么判断对象是一个特性呢?看对象的结尾是否以Attribute结尾,只要以Attribute结尾的基本上是特性。
特性在定义时,建议以Attribute结尾。特性肯定是一个类,必须继承Attribute。Atribute是特性的基类。
2。反射?
反射是指在程序运行中,查看、操作其他程序集或者自身的元数据的各种信息(类、方法,属性、变量、对象等)的行为。C#中的反射(Reflection)是一种强大的功能,允许你在运行时检查和操作程序集、类型和对象的信息,基本上,使用反射可以在代码运行时检查和操作指定的类及其成员。C#反射的原理主要基于元数据(与C#特性相似),即程序集中存储的有关类型、方法等的信息。因为反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性。
反射就是为了拿到各种元素对应的标签。Reflection反射。使用反射时,代码性能低,因为反射使用了装箱和拆箱。
// 1。反射拿类型Type type3 = typeof(Student);Student t = new Student(); // 没有使用反射,直接创建实例Type type4 = t.GetType();// 2。通过类型获取字段,属性,方法,// 通过反射创建实例// Assembly.Load("1.特性")加载程序集,CreateInstance(完整的对象的名称)用加载的程序集在创建一个程序集中的对象的实例// 如果加载的程序集在当前项目中的bin/debug中不存在,会加载失败。Assembly assembly = Assembly.Load("1.特性"); // 拿程序集// 使用反射技术创建程序集中的某个类的实例。装箱的操作object t1 = assembly.CreateInstance("_1.特性.Student"); // 类似于Student t = new Student();//FieldInfo fieldInfo = type3.GetField("_id"); // 获取单个字段//fieldInfo.SetValue(t1, 1); // 给字段设置值 相当于_id=10, 报错:私有的无法访问FieldInfo fieldInfo = type3.GetField("myId");int myId = (int)fieldInfo.GetValue(t1); // 获取公开的字段值,使用装箱和拆箱Console.WriteLine(myId);fieldInfo.SetValue(t1, 20); // 设置字段值int myId2 = (int)fieldInfo.GetValue(t1);Console.WriteLine(myId2);Console.WriteLine("-----------------");FieldInfo[] fieldInfos = type3.GetFields();foreach (var item in fieldInfos){Console.WriteLine(item.GetValue(t1));}Console.WriteLine("-----------------");PropertyInfo propertyInfo1 = type3.GetProperty("Name"); // 拿单个属性propertyInfo1.SetValue(t1, "张三"); // 设置属性string name = (string)propertyInfo1.GetValue(t1); // 获取属性值Console.WriteLine(name);Console.WriteLine("-----------------");PropertyInfo[] propertyies = type3.GetProperties(); // 拿所有公开属性foreach (var item in propertyies){if (item.Name == "Id") // 判断属性是不是Id属性{item.SetValue(t1, 100);}if (item.Name == "Name"){item.SetValue(t1, "李四");}Console.WriteLine(item.GetValue(t1));}Console.WriteLine("-----------------");MethodInfo methodInfo = type3.GetMethod("Method2"); // 拿方法methodInfo.Invoke(t1, new object[] { "ABC", 10000 }); // 调用方法Type h1 = type3.GetNestedType("Hello"); // 拿到Student类下的Hello类的类型object hIns = assembly.CreateInstance(h1.FullName);PropertyInfo pInfo = h1.GetProperty("Name");object value = pInfo.GetValue(hIns);Console.WriteLine(value);// 用反射的技术把libs/ClassLibrary1.dll中的Class1应用一下。// 直接使用不可能了,原因:此类库没有在当前程序中引用。// Class1 class1 = new Class1(); // 代码出错// 1。先加载程序集string assemblyFile = Path.Combine(Environment.CurrentDirectory, "../../libs/ClassLibrary1.dll");Assembly class1Assembly = Assembly.LoadFrom(assemblyFile);// 2。创建某个类的实例object class1 = class1Assembly.CreateInstance("ClassLibrary1.Class1");Type class1Type = class1.GetType();// 3。拿成员//FieldInfo//MethodInfo//PropertyInfo//MemberInfo其实是FieldInfo,MethodInfo,PropertyInfo等的综合体Console.WriteLine("-----------------");MemberInfo[] members = class1Type.GetMembers(); // 获取类的所有的成员foreach (var item in members){// 判断某个成员是否是继承的成员, item.DeclaringType == item.ReflectedType非继承的成员if (item.DeclaringType == item.ReflectedType){// 判断成员是否是属性if (item.MemberType == MemberTypes.Property){PropertyInfo p = item as PropertyInfo;Console.WriteLine($"属性名:{p.Name},属性值:{p.GetValue(class1)}");}// 判断成员是否是方法if (item.MemberType == MemberTypes.Method){MethodInfo m = item as MethodInfo;// IsSpecialName如果返回true表示是特殊的方法(由属性生成的get/set访问器。Console.WriteLine($"方法名:{m.Name},是否是特殊方法:{m.IsSpecialName}");if (!m.IsSpecialName){if (m.Name == "Method1"){Console.Write("执行结果:");m.Invoke(class1, null); // Invoke调用方法}else if (m.Name == "Method2"){object result = m.Invoke(class1, new object[] { "hello world" });Console.WriteLine($"执行结果:{result}");}}}};}
结果

反射重要的API?
t.GetField();// FieldInfo类,拿类的字段
t.GetProperty();// PropertyInfo类,拿类的属性
t.GetMethod(“SayHello”) // MethodInfo类,拿方法的元数据。
t.GetConstructor() // ConstructorInfo类,拿类的构造函数
t.GetEvent();// EventInfo类,拿类的事件
t.GetCustomAttribute();// Attribute类,拿类的特性
typeof() 和 GetType() // 获取类型
Invoke() 和 InvokeMember() // 调用相应的成员
SetValue(),GetValue()// 设置属性,获取属性
相关文章:
C#特性和反射
1。特性概念理解? 特性(Attribute)是用于在【运行时】传递程序中各种元素(比如类、属性、方法、结构、枚举、组件等)行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所…...
蓝桥杯刷题周计划(第三周)
目录 前言题目一题目代码题解分析 题目二题目代码题解分析 题目三题目代码题解分析 题目四题目代码题解分析 题目五题目代码题解分析 题目六题目代码题解分析 题目七题目代码题解分析 题目八题目代码题解分析 题目九题目代码题解分析 题目十题目代码题解分析 前言 大家好&#…...
mysql5.x和mysql8.x查看和设置隔离级别
MySQL的隔离级别 级别标志值描述读未提交READ-UNCOMMITTED0存在脏读、不可重复读、幻读的问题读已提交READ-COMMITTED1解决脏读的问题,存在不可重复读、幻读的问题可重复读REPEATABLE-READ2mysql 默认级别,解决脏读、不可重复读的问题,存在幻…...
3.17学习总结
写了两道题 刚开始用的之前做组合输出的方法,时间超限了,想不出怎么优化,后面看了题解,代码如下 #include <stdio.h> #include <stdlib.h> int n,min2e9; int a[11],b[11]; //搜索 void hly(int s,int x,int y) {//当…...
Blender材质 - 层权重
层权重 混合着色器 可以让 面朝向的一面显示一种材质 另一面显示另一种材质 就能实现挺不错的材质效果 移动视角 材质会跟着变化 有点类似虚幻的视差节点BumpOffset...
【JavaEE】Spring Boot 日志
目录 一、日志概述二、使用日志2.1 打印日志2.2 日志框架2.2.1 门面 / 外观 模式 2.3 日志级别2.3.1 六大分类2.3.2 使用 2.4 日志级别配置2.5 日志的持久化2.6 日志文件分割2.7 日志文件格式2.8 Slf4j 简单打印日志 一、日志概述 ⽇志主要是为了发现问题, 分析问题, 定位问题…...
Qt中的 #include “xxxx.moc“ 说明
Qt中的 #include “xxxx.moc” 说明 在Qt开发中,有时会看到在cpp文件末尾包含 #include "xxxx.moc" 这样的代码。这种做法主要用于以下情况: 使用场景 当你在非头文件中定义了一个包含Q_OBJECT宏的类时,需要包含对应的.moc文件。…...
如何用solidworks画齿轮
齿轮还是很有技术含量的,专业名词太多看不懂, 只会画 (这个东西不能自己想当然画, 齿轮之间不啮合是很有问题的,会积累磨损) 步骤1 打开设计库里的toolbox 选择正齿轮,右键生成零件 需要改的有几个关键的地方,我是只知道内圆外圆所以,对我来说最重要的是标称轴直径 (即正中间…...
详解布隆过滤器及其模拟实现
目录 布隆过滤器 引入 概念 工作原理 模拟实现布隆过滤器 哈希函数集 布隆过滤器基本框架 add函数(添加到布隆过滤器中) contains函数(判断是否存在该值) 完整代码 布隆过滤器的删除 布隆过滤器的误判率 布隆过滤器的…...
element-plus中DatePicker 日期选择器组件的使用
1.选择某一天 代码: <el-date-pickerv-model"invoice_date"type"date"placeholder"请选择日期"style"width: 200px;"clearable /> 运行效果: 问题所在:这个数据的格式不是我们后端需要的那种&…...
SvelteKit 最新中文文档教程(4)—— 表单 actions
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...
力扣hot100二刷——二叉树
第二次刷题不在idea写代码,而是直接在leetcode网站上写,“逼”自己掌握常用的函数。 标志掌握程度解释办法⭐Fully 完全掌握看到题目就有思路,编程也很流利⭐⭐Basically 基本掌握需要稍作思考,或者看到提示方法后能解答⭐⭐⭐Sl…...
企业安全——数据泄露防护
0x00 前言 本篇对数据泄露防护方面的内容进行汇总和总结,为抛砖引玉的内容 0x01 数据隔离 数据隔离是防止数据泄露的一个非常好的方式,通常的隔离方式有 主机/服务器隔离网络隔离介质隔离 0x02 数据丢失预防 主要防止数据丢失的方法就是DLP&#x…...
字符串哈希从入门到精通
一、基本概念 字符串哈希是将任意长度的字符串映射为固定长度的哈希值(通常为整数)的技术,核心目标是实现O(1)时间的子串快速比较和高效查询。其本质是通过数学运算将字符串转换为唯一性较高的数值,例如: …...
C语言:编程设计猜数游戏
先由计算机想一个数给用户猜,如果猜对了,提示“right!”,猜错了,提示“wrong!及大小” 思路:用随机函数rand()取到计算机想的数 代码: #include <stdio.…...
地下车库智能停车位指引系统方案(还有缺陷)
一、系统核心技术架构 通过车牌识别+车位检测+室内定位+路径规划四大技术模块实现全自动指引: 二、关键技术方案 1. 车辆身份识别与入场触发 车牌识别(LPR)技术 入口处部署高清摄像头,自动识别车牌并关联车辆信息(如会员、临时车)。触发逻辑:识别成功后抬杆放行,同时…...
Docker 使用指南
Docker 是一种开源的容器化平台,它通过使用容器来进行应用程序的打包、分发和部署。下面是 Docker 的基本概念和优势: 容器化:Docker 使用容器来封装应用程序及其所有依赖项,使其能够在任何环境中运行,并且与底层系统隔…...
win10 c++ VsCode 配置PCL open3d并显示
win10 c VsCode配置PCL open3d并显示 一、效果图二、配置步骤2.1 安装vscode2.2 pcl-open3d配置2.3 vscode中设置 三、测试代码四、注意事项及后续 一、效果图 二、配置步骤 2.1 安装vscode vscode下载链接 下载中文插件、c相关插件 2.2 pcl-open3d配置 1)下载…...
Vala 开发环境搭建
介绍 Vala 是一种使用现代高级抽象的编程语言,与用 C 语言编写的应用程序和库相比,没有施加额外的运行时要求,也不需要使用不同的 ABI。 Vala 使用 GObject 类型系统,并具有额外的代码生成例程,使面向 GNOME 堆栈变得简…...
【网页】自制流光卡片
概述 小红书有个博主自己搞的笔记排版工具叫“流光卡片”,类似的还有个Markdown排版工具叫MD2Card。 我这个版本类似,但是自己写的东西,控制性更好。 初期就写了个静态页面,后期结合Godot快速生成,并可能结合JS库&a…...
【数据结构】栈与队列:基础 + 竞赛高频算法实操(含代码实现)
什么是栈?什么是队列? 什么是先进后出?什么是先进先出? 了解基础之后,又如何用来写算法题? 带着这些疑问,让我带领你,走进栈与队列的世界 栈与队列 栈: 1、栈的基本…...
CSP-J/S冲奖第18天:真题解析
解题步骤 读取输入:首先读取整数n,然后读取n个正整数并存储在一个数组或容器中。 排序数组:对数组进行排序,以便后续使用双指针法高效查找。 遍历数组:对于每个数target,检查是否存在另外两个不同的数a和…...
【linux】虚拟机执行sudo yum isntall perl报错 could not retrieve mirrorlist htt:
项目场景: 提示:虚拟机安装拓展包,sudo yum install perl Virtualbox 在不安装增强功能扩展的情况下, 无法自适应分辨率和共享剪切板等操作 问题描述 原因分析: 提示:这里填写问题的分析: 出现这个错误是因…...
旅游类小程序界面设计
产品概述 艾啦游是一款互联网旅游类小程序,致力于国内精品旅游,以及拥有自由行、专属热榜单、出行攻略等诸多功能,汇聚了许多国内的人气景点,与诸多城市的酒店也保持合作,打造一体式旅行服务,更有不断上新…...
DQN 玩 2048 实战|第三期!优化网络,使用GPU、Env奖励优化
视频讲解: DQN 玩 2048 实战|第三期!优化网络,使用GPU、Env奖励优化 1. 仅考虑局部合并奖励:目前的奖励只设置为合并方块时获得的分数,只关注了每一步的即时合并收益,而没有对最终达成 2048 这个…...
【python】http post 在body中传递json数据 以发送
http post 在body中传递json数据 以发送,json的格式非常重要这里要传递json对象,而不是一个json字符串 传递post一个 JSON 字符串 是ok的 是的, {"rsource_rhythm_action_list": {"name": "AI_\\u6708\\u4eae\\u…...
Linux错误(2)程序触发SIGBUS信号分析
Linux错误(2)之SIGBUS错误分析 Author: Once Day Date: 2025年3月12日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: Linux实践记录_Once_day的博…...
【Halcon】灰度不均解决方案
目录 1、平场校正 2、形态学背景估计 3、频域滤波抑制低频光照不均 4、动态局部自适应 1、平场校正 原理:通过白场(White Image)和黑场(Black Image)图像,手动计算校正系数 * 读取图像 read_image(ImageRaw, raw_image) // 原始图像 read_image(ImageWhite, …...
滑动窗口算法详解:从入门到精通
目录 引言 1. 滑动窗口算法简介 2. 滑动窗口的基本思想 3. 滑动窗口的应用场景 3.1 最大子数组和 3.2 最小覆盖子串 3.3 最长无重复字符子串 4. 滑动窗口的实现步骤 5. 滑动窗口的代码示例 6. 滑动窗口的优化技巧 6.1 使用哈希表记录字符频率 6.2 使用双指针维护窗口…...
JAVA数据库技术(一)
JDBC 简介 JDBC(Java Database Connectivity)是Java平台提供的一套用于执行SQL语句的Java API。它允许Java程序连接到数据库,并通过发送SQL语句来查询、更新和管理数据库中的数据。JDBC为不同的数据库提供了一种统一的访问方式,使…...
