最新要闻
- 88年后入土为安 云南禄劝隆重安葬21具红军烈士遗骸
- 新消息丨厂商为何要封杀32位APP?真实原因揭开
- 比商超便宜一半多!伊利巧乐兹大促:券后每支2.4元起
- 3090 Ti能抵7200元 iGame以旧换新7日开启:RTX 40显卡这下真的便宜了 天天视讯
- 焦点快播:1049元 创维推出新款23.8电竞显示器:165Hz Fast IPS屏
- 每日聚焦:村里又来年轻人 发展动力更强劲
- 重磅!“听音写稿”成真 讯飞听见重大升级:一段录音 一键成稿 今热点
- 热资讯!菜鸟驿站爆改大征集:夜间自助取件 这5个城市方便了
- 国产AI逆袭!一图看懂讯飞星火:文本生成、知识问答、数学三大能力已超越ChatGPT
- 理想汽车五一出行报告出炉:行程1.44亿公里、一半都在烧油
- 世界聚焦:山东黄金董事长李航:预计金价仍有进一步上涨空间
- 今日视点:首座深远海浮式风电平台完成海上安装
- 头条:男孩掉入黄河被救 家长抬羊登门拜谢 网友:知恩图报的正确打开方式
- 遥遥领先!讯飞星火认知大模型可自动创作 生成虚拟人朗读-每日消息
- 《银河护卫队3》上映2天票房破7000万 豆瓣评分高达8.7-天天热头条
- 18.98万起售 曝比亚迪海豹冠军版接受预定:比现款便宜多了
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
世界热点评!C#高级编程--反射与特性
C#高级编程--反射与特性
(资料图片)
特性attribute,特性是一种允许我们向程序集添加元数据的语言结构。特性是用于保存程序结构信息的特殊的类;
目标target,应用/添加了特性的程序结构(program construct)叫做目标;
消费者consumer,用来获取和使用元数据/特性的程序叫做特性的消费者;
.NET有很多内置特性,也可以自定义特性;将特性用于描述程序结构;
编译器获取源代码,并从特性产生关于源代码的描述信息(元数据),然后将元数据放到程序集中;
消费者程序读取特性/元数据,编译器既生成特性,同时也消费特性;
Type对象:
对于程序中用到的每一个类型,CLR都会创建一个包含这个类型的信息的Type对象;
不管该类型创建多少个实例,都只有一个Type对象,并且同时关联到该类及该类的所有实例;
获取Type对象的三种方法
分类 | 静态方法 | 关键字 | 实例方法 |
方法 | Type.GetType() | typeof() | object.GetType() |
参数 | string className | Class | 无参 |
示例 | Type t1 = Type.GetType("Person"); | Type t2 = typeof(Person); | Person p = new Person(); Type t3 = p.GetType(); |
错误示例 | //t4 = Type.GetType(Person); //错误:静态方法不能传入类名 //t4 = Type.GetType(p); //错误:静态方法不能传入类对象 | //t4 = typeof("Person"); //错误:不能传入类名 字符串 //t4 = typeof(p); //错误:不能传入类对象 |
//获取type对象的三种方法
//1、Type类的静态方法,只能传入类名字符串作为参数
Type t1 = Type.GetType("Person");
//2、使用typeof关键字,只能传入类名作为参数,而不能传入字符串或者类对象;
Type t2 = typeof(Person);
//3、使用object的实例方法,实例化的对象,调用基类object的GetType方法,无需参数;
Person p = new Person();
Type t3 = p.GetType();
//错误示例
Type t4;
//t4 = Type.GetType(Person); //错误:静态方法不能传入类名
//t4 = Type.GetType(p);//错误:静态方法不能传入类对象
//t4 = typeof("Person");//错误:typeof不能传入类名字符串
//t4 = typeof(p);//错误:typeof不能传入类对象
元数据metadata,有关程序及其类型的数据被称为元数据,它们保存在程序的程序集中;
反射reflection,程序在运行时,可以查看其他程序集或自身程序集的元数据。运行中程序查看元数据的行为叫做反射;
特性目标
All | 所有 | 可以对任何应用程序元素应用属性 |
Constructor | 构造函数 | 可以对构造函数应用属性 |
Method | 方法/函数 | 可以对方法应用属性 |
Property | 属性 | 可以对属性 (Property) 应用属性 (Attribute)。 |
Field | 字段 | 可以对字段应用属性 |
Parameter | 参数 | 可以对参数应用属性。 |
GenericParameter | 泛型参数 | 可以对泛型参数应用属性。 目前,此属性仅可应用于 C#、Microsoft 中间语言 (MSIL) 和已发出的代码中。 |
ReturnValue | 返回值 | 可以对返回值应用属性 |
Delegate | 委托 | 可以对委托应用属性 |
Event | 事件 | 可以对事件应用属性 |
Class | 类 | 可以对类应用属性 |
Struct | 结构体 | 可以对结构应用属性,即值类型。 |
Interface | 接口 | 可以对接口应用属性 |
Enum | 枚举 | 可以对枚举应用属性 |
Assembly | 程序集 | 可以对程序集应用属性 [assembly:MyAttribute(Parameters)] |
Module | 模块 | 可以对模块应用属性。Module引用的是可移植可执行文件(.dll 或 .exe),而不是 Visual Basic 标准模块。 [module:MyAttribute(Parameters)] |
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field),
AllowMultiple=false,Inherited=false]
public class FieldNameAtrribute:Attribute{
private string _fieldName;
public FieldNameAtrribute(string fieldName){_fieldName=fieldName;}
}
特性的特点:
- 特性可以用到那些程序元素上(特性目标AttributeTargets);
- 特性是否可以多次使用(AllowMultiple);
- 特性用到基类上或者接口上时,是否允许子类继承(Inherited);
- 特性需要那些参数(包括可选参数和必选参数);
特性分类(按用途):
- 用于编译器的特性(影响编译过程,如条件编译特性Conditional,过期标记特性Obsolete);
- 用于特性类的特性(指定自定义特性类的一些特点,如指定自定义特性用途的特性AttributeUsage);
- 用于标记元数据的自定义特性(为程序元素添加描述信息的元数据);
消费(查找使用)特性的本质:反射从程序集中读取元数据(特性),并实例化他们所表示的特性类。
特性分类(按程序元素)
- 全局特性,应用于程序集,必须显示指定;
- 局部特性,应用于其他程序元素(可以隐式或显示指定目标元素);
使用特性时的注意事项:
- 使用特性时,可以省略特性类名后的Attribute,当然也可以不省略,二者等价;
- 使用特性时,小括号中的参数有两类:位置参数和命名参数;
- 位置参数是指该特性类的构造函数中的参数;
- 命名参数并不是构造函数中的参数,而是该特性类中的公共字段/属性(这一点与普通类不同);
示例代码
#define condition1#undef condition1using System;using System.Data;using System.Diagnostics;using System.IO;using System.Linq;using System.Reflection;using System.Runtime.InteropServices;namespace ConsoleCore3{ class Program { static void Main(string[] args) { AttributeTest(); } static void AttributeTest() { Person p = new Person("tom"); //通过Person对象获取该类的Type对象 Type t = p.GetType(); //判断该程序元素上是否定义(添加)了某个特性 bool isDefined = t.IsDefined(typeof(SerializableAttribute)); Console.WriteLine($"SerializableAttribute defined:{isDefined}");//True //通过属性名获取属性的元数据(描述信息) PropertyInfo pInfo_Name = t.GetProperty("Name"); //通过反射获取属性类型 bool isString = pInfo_Name.PropertyType == typeof(String); Console.WriteLine($"pName is string:{isString}"); //通过反射获取属性值 Console.WriteLine($"Name={pInfo_Name.GetValue(p)}"); //通过反射为属性赋值 pInfo_Name.SetValue(p, "王英"); Console.WriteLine($"Name={p.Name}"); //通过反射获取属性上是否添加(定义)了某个特性 isDefined = pInfo_Name.IsDefined(typeof(FieldNameAttribute)); Console.WriteLine($"FieldNameAttribute defined:{isDefined}");//True //获取字段上添加的特性对象(元数据) FieldNameAttribute attr = pInfo_Name.GetCustomAttribute(typeof(FieldNameAttribute)) as FieldNameAttribute; //从读取的特性中获取元数据 Console.WriteLine($"FieldName={attr.FieldName},Comment={attr.Comment}"); //通过反射获取某个方法 MethodInfo mInfo_SayHi = t.GetMethod("SayHi"); //通过反射调用方法 mInfo_SayHi.Invoke(p, null); //通过反射获取某个方法--有参数 MethodInfo mInfo_Eat = t.GetMethod("Eat"); //调用有参方法 mInfo_Eat.Invoke(p, new object[] { "馒头" }); //输出结果 //SerializableAttribute defined:True //pName is string:True //Name = tom //Name = 王英 //FieldNameAttribute defined:True //FieldName = 姓名, Comment = 这是姓名属性 //hello world //馒头 真好吃 } static void UnsafeTest() { unsafe { // 错误 CS0208 无法获取托管类型(“Person”)的地址和大小,或者声明指向它的指针 //int size = sizeof(Person); int size = sizeof(double);//8 Console.WriteLine(size); Student s = new Student(); //错误 CS0208 无法获取托管类型(“Program.Student”)的地址和大小,或者声明指向它的指针 //Student* sp = & s; } var p = new Person(); //CS0233“Person”没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用 // int size = sizeof(Person) } unsafe struct Student { string name; int age; } static void AssemblyTest2() { const string className = "mynamespace.Calculator"; Assembly ass = Assembly.LoadFrom(@"D:\VSFile2019\ConsoleCore1\calculator\bin\Debug\netcoreapp3.1\calculator.dll"); //使用Invoke调用函数 //CreateInstance的参数string typeName,必须是 命名空间.类名 的格式; //typeName参数区分大小写 object cal = ass.CreateInstance(className); Console.WriteLine(cal); //calculator.Calculator //GetMethod的参数name区分大小写; //Invoke第一个参数是类的实例化对象,第二个参数是所调用的函数的参数列表,以object数组形式传递 //object[]中的元素个数必须和函数所需参数个数完全一致,否则报错; //object[]中的元素类型必须与参数与类型一致,或者能够隐式转换为目标类型,否则报错; object res = cal.GetType().GetMethod("Add").Invoke(cal, new object[] { 1.5, "a" }); Console.WriteLine(res);//3.5 //使用动态类型调用函数 dynamic calculator = ass.CreateInstance(className); //动态类型没有智能提示,容易出现拼写错误 dynamic result = calculator.Add(2.2, 3.0); Console.WriteLine(result);//5.2 //调用一个不存在的函数,编译器不会报错,只有等到运行时才会出现异常; //:“"mynamespace.Calculator" does not contain a definition for "Pow"” //calculator.Pow(2, 3); //大小写拼写错误,编译器不会有智能提示,只有等到运行时才会出现异常; //:“"mynamespace.Calculator" does not contain a definition for "add"” calculator.add(5, 6); } static void AssemblyTest() { //通过dll名称 获取程序集 Assembly ass = Assembly.Load("itextsharp"); //itextsharp, Version=5.5.7.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca Console.WriteLine(ass); // Console.WriteLine("types--------------"); // ass.GetTypes().ToList().ForEach (c => Console.WriteLine(c)) ; Assembly ass2 = Assembly.LoadFile(@"D:\VSFile2019\仲裁文档标准化项目V1.0\AxInterop.DSOFramer.dll"); //AxInterop.DSOFramer, Version=2.2.0.0, Culture=neutral, PublicKeyToken=null Console.WriteLine(ass2); ass2.GetTypes().ToList().ForEach(c => Console.WriteLine(c)); Console.ReadLine(); } static void TypeTest2() { Type t = typeof(Person); Console.WriteLine(t.BaseType); //System.Object t.GetConstructors().ToList().ForEach(c => Console.WriteLine(c));//Void .ctor() Console.WriteLine("properties--------------"); t.GetProperties().ToList().ForEach(c => Console.WriteLine(c)); Console.WriteLine("fields--------------"); t.GetFields().ToList().ForEach(c => Console.WriteLine(c)); Console.WriteLine("members--------------"); t.GetMembers().ToList().ForEach(c => Console.WriteLine(c)); //System.Object //Void.ctor() //properties-------------- //Int32 Age //System.String Name //fields-------------- //Int32 id //members-------------- //Int32 get_Age() //Void set_Age(Int32) //System.String get_Name() //Void set_Name(System.String) //Void SayHi() //System.Type GetType() //System.String ToString() //Boolean Equals(System.Object) //Int32 GetHashCode() //Void.ctor() //Int32 Age //System.String Name //Int32 id } static void TestType() { //获取type对象的三种方法 //1、Type类的静态方法,只能传入类名字符串作为参数 Type t1 = Type.GetType("Person"); //2、使用typeof关键字,只能传入类名作为参数,而不能传入字符串或者类对象; Type t2 = typeof(Person); //3、使用object的实例方法,实例化的对象,调用基类object的GetType方法,无需参数; Person p = new Person(); Type t3 = p.GetType(); //错误示例 Type t4; //t4 = Type.GetType(Person); //错误:静态方法不能传入类名 //t4 = Type.GetType(p);//错误:静态方法不能传入类对象 //t4 = typeof("Person");//错误:typeof不能传入类名字符串 //t4 = typeof(p);//错误:typeof不能传入类对象 } //条件编译特性,该特性使用者为编译器 //因此只需在对应方法上标记该特性,而无需手动通过反射获取该特性 //如果定义了宏 condition1,则编译该方法,否则编译器忽略该方法 [Conditional("condition1")] static void TraceMessage(string s) { Console.WriteLine(s); } static void ConditionalTest() { TraceMessage("开始");//如果定义了宏#define condition1,编译器就编译本行代码,否则就忽略 Console.WriteLine("Hello World!"); TraceMessage("结束");//如果定义了宏#define condition1,编译器就编译本行代码,否则就忽略 } } [Serializable] class Person { // [FieldName("Age")] 该特性只能在属性上使用,而不能在字段上使用AttributeTargets.Property //如果想要在多种程序元素上使用,可以使用按位或运算符,连接各种目标元素 //AttributeTargets multiTargets = AttributeTargets.Field|AttributeTargets.Property|AttributeTargets.ReturnValue; public Person() { } public Person(string name) { Name = name; } public int id; [FieldName("Age")] // [FieldName("Age")] 该特性不能在同一个程序元素上重复使用 AllowMultiple = false public int Age { get; set; } [FieldName("姓名", Comment = "这是姓名属性")] public string Name { get; set; } public void SayHi() { Console.WriteLine("hello world"); } public void Eat(string food) { Console.WriteLine($"{food} 真好吃"); } } //用于描述特性用途的特性 // AttributeTargets特性目标,描述该特性可以用于哪些程序元素 //AllowMultiple 是否允许在同一个程序元素上添加多次 //Inherited 是否允许子类继承该特性 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class FieldNameAttribute : Attribute { public string Comment { get; set; } private string _fieldName; public FieldNameAttribute(string fieldName) { _fieldName = fieldName; } public string FieldName { get => _fieldName; set => _fieldName = value; } }}
关键词:
世界热点评!C#高级编程--反射与特性
88年后入土为安 云南禄劝隆重安葬21具红军烈士遗骸
新消息丨厂商为何要封杀32位APP?真实原因揭开
比商超便宜一半多!伊利巧乐兹大促:券后每支2.4元起
3090 Ti能抵7200元 iGame以旧换新7日开启:RTX 40显卡这下真的便宜了 天天视讯
焦点快播:1049元 创维推出新款23.8电竞显示器:165Hz Fast IPS屏
每日聚焦:村里又来年轻人 发展动力更强劲
推荐6个我经常逛的“小网站”,嘿嘿嘿!!!
【全球播资讯】用Radare2模拟shellcode运行
全球时讯:数仓建模规范--非常全
Vue2的生命周期 每日速递
美国制裁升级,推动国产化网卡发展刻不容缓
重磅!“听音写稿”成真 讯飞听见重大升级:一段录音 一键成稿 今热点
热资讯!菜鸟驿站爆改大征集:夜间自助取件 这5个城市方便了
国产AI逆袭!一图看懂讯飞星火:文本生成、知识问答、数学三大能力已超越ChatGPT
理想汽车五一出行报告出炉:行程1.44亿公里、一半都在烧油
世界聚焦:山东黄金董事长李航:预计金价仍有进一步上涨空间
新消息丨前端开发环境搭建踩坑笔记——npm install node-sass安装失败的解决方案
C/C++代码内捕获异常发生时的调用栈
天天即时看!如何通过代码接入手机在网状态 API
不一样的设计模式——— 重新理解6大原则[外篇]
今日视点:首座深远海浮式风电平台完成海上安装
头条:男孩掉入黄河被救 家长抬羊登门拜谢 网友:知恩图报的正确打开方式
遥遥领先!讯飞星火认知大模型可自动创作 生成虚拟人朗读-每日消息
《银河护卫队3》上映2天票房破7000万 豆瓣评分高达8.7-天天热头条
18.98万起售 曝比亚迪海豹冠军版接受预定:比现款便宜多了
天天速读:科大讯飞刘庆峰:讯飞星火大模型中文能力已经超过ChatGPT
Idea编译:Java找不到符号(终极解决方案篇)_天天要闻
分布式场景下,如何对外提供易变的服务,打造可靠的注册中心?
每日消息!涨知识!你不知道的中国手机号码的编码和划分规则
汽车的供电状态
江阴枪击案嫌犯或已跟踪受害人半年具体是什么情况
哨兵模式立大功 理想L9遭遇奥迪“开门杀”:清清楚楚拍下全过程
天天动态:1.6亿赔款谁来出?承重墙被砸现高楼内仍有人居住 网友称楼体扭曲变形
国产最强AI来了!讯飞星火认知大模型发布:中文超越ChatGPT 英文已接近
要闻:传比亚迪电池配套欧版特斯拉 官方:不予置评
当前区块链研究领域的前沿技术和研究方向
快克智能(603203):短期承压不改趋势 半导体业务落地打开新空间|环球讯息
全球报道:没有金刚钻别揽瓷器活 特斯拉Model Y涉水越野:“脸”都烂了
同比猛涨128% 奇瑞4月销量出炉:狂卖12.7万辆站稳自主第一梯队 天天快播报
环球热头条丨AIGPT中文版(无需魔法)最简单的方式实现AI绘画
当前聚焦:热门的免费 API 合辑整理
.NET几种微服务框架,你用过吗?
热点聚焦:两个系统之间跳转免密登录
承重墙被砸1.6亿赔款谁来出? 法律人士:租户、施工队责任重大
中国电子云成为政企信创促进中心首批成员单位
科济药业AB011联合用药一线治疗胃癌获批临床 全球热文
梦幻西游检查更新失败是什么原因?梦幻西游检查更新失败怎么解决?
美剧《西游ABC》新海报发布:杨紫琼观音、吴彦祖美猴王下凡_世界资讯
男子花32万买二手奔驰获赔98万:车商隐瞒是泡水报废车
戴尔xps13怎么增加固态硬盘?戴尔xps13笔记本参数
富士宝电磁炉质量怎么样?富士宝电磁炉故障大全
多玩盒子是什么时候出的?多玩盒子怎么卸载?
索尼投影机灯泡时间怎么清零?索尼投影机驱动怎么安装?
教师节是中国的还是国际的?教师节为什么定在9月10号?
天天亮点!手机内存卡怎么加密码_手机内存卡怎么加密
旷亮无比的意思是什么?旷亮无比的天空仿写三个词语
林书豪现在在哪个球队?林书豪的父母简介
生肖是按农历还是阳历计算的?96属鼠跟什么属相更配?正确的属相划分时间是什么?
什么是文创产品?文创产品的功能有哪些?文创发展趋势是什么?
一文详解如何在 ChengYing 中通过产品线部署一键提升效率-每日热门
今日快看!存货、负债、坏账持增 经营现金流量净额转负 宏工科技能过会么
特斯拉索赔500万名誉维权案将开庭 被告方为“刹车失灵”车主张女士:积极应诉 每日热议
达人契约能增加多少伤害(达人契约)
MYSQL数据库基础--MySQL子查询怎么操作?_世界百事通
易基因:2023年植物表观转录组研究的最新进展(m6A+m5C)|深度综述
32位进程设置大地址(3G)空间-世界滚动
Unix教程_编程入门自学教程_菜鸟教程-免费教程分享 最新消息
讯息:抖音芭比q是什么意思梗_网络语芭比q是什么意思
天天实时:5月26上映!迪士尼发真人版《小美人鱼》极清剧照:黑小美人鱼好看吗?
德国进口:Knoppers榛子巧克力威化饼干29.9元/13包|环球热闻
漫威回归内地首作!《黑豹2》今日上线网播:“优爱腾”同步上线
天天最新:智联招聘:应届毕业生选择单位就业比例升至57.6%
解析智慧园区的发展瓶颈
Linux下搭建Python2.7环境 环球观焦点
今日快看!git~分支管理规范
余维佳退出?世纪证券官宣新董事长和新总经理,去年投行资管双丰收|世界消息
立夏吃一蛋力气长一万!夏天模式开启:你那有什么习俗?_每日热讯
4999元起!小米13/13 Ultra限量定制色今日首发:三款新配色|全球热议
39999元买它!索尼:我们是游戏电视的引领者
强劲非农数据重燃紧缩预期 美债收益率全线回升 全球快资讯
凝望是什么意思_凝望的意思 天天微头条
环球新资讯:4倍降温吹凉风!小米米家智能蒸发式冷风扇上架:众筹价489元
全球最资讯丨Mate50立功!华为站起来 跻身前十背后:4G打败5G 品牌溢价高买手机就认它
天天热资讯!学系统集成项目管理工程师(中项)系列18a_进度管理(上)
恩施州气象台发布雷电黄色预警【III级/较重】【2023-05-06】
世界热门:ChatGPT最全提示词Prompts总结,看这一篇就够了!
Unity开发Hololens2—交互发布配置
中国高铁真狂魔!一张照片里 五条隧道、五座大桥 观热点
喜欢在沙里挖陷阱的小虫子叫啥?儿时经常玩 如今一斤卖6000 世界观速讯
环球今日报丨研究称脂肪过多会降低智商:吓得我感觉吃个烧烤压压惊
全球热议:火锅里咬起来咯吱咯吱的“贡菜”:究竟是什么?
30%的苹果税不好赚了 iOS 17大改:第三方应用来了
环球视讯!BLG晋级正赛,队内语音很欢乐,Bin想冲进敌方泉水,随便赢
大一一封家书范文500字(热门27篇) 环球动态
灵跃武器怎么转换_灵跃武器怎么获得
菲梦少女第三季为什么禁播_菲梦少女第三季免费版_天天快资讯
千万粉丝网红吃播小贝饿了带货因虚假宣传被罚46万:调理牛排宣传为原切
全球短讯!AMD最强核显称霸掌机!干掉RTX 2050、逼近GTX 1650 Ti
金仓数据库KingbaseES 两表关联Update的两种写法与性能