C#特性与反射知识梳理

C#中的**特性(Attributes)反射(Reflection)**是两个非常重要的概念,它们通常用于代码的元编程,允许你在运行时获取类型信息并对其进行操作。下面对这两个概念进行详细梳理:

一、C#中的特性(Attributes)

特性是C#中的一种机制,允许你为类、方法、属性、字段、参数等代码元素添加额外的元数据。特性可以在编译时进行检查,也可以在运行时通过反射获取。

1. 特性的定义

特性是从 System.Attribute 基类派生的类。例如:

csharp

复制编辑

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class MyCustomAttribute : Attribute { public string Name { get; set; } public MyCustomAttribute(string name) { Name = name; } }

在上面的代码中,MyCustomAttribute 是一个自定义特性,AttributeUsage 特性指定了它可以应用到类和方法上。

2. 特性的使用

定义了特性后,可以像下面这样将它应用到代码中的某个元素:

csharp

复制编辑

[MyCustomAttribute("Example")] public class MyClass { [MyCustomAttribute("Method Example")] public void MyMethod() { } }

在这个例子中,MyCustomAttribute 被应用到类 MyClass 和它的 MyMethod 方法上。

3. 获取特性

可以使用反射来获取应用于类型或成员的特性。例如:

csharp

复制编辑

var type = typeof(MyClass); var method = type.GetMethod("MyMethod"); var classAttribute = (MyCustomAttribute)Attribute.GetCustomAttribute(type, typeof(MyCustomAttribute)); var methodAttribute = (MyCustomAttribute)Attribute.GetCustomAttribute(method, typeof(MyCustomAttribute)); Console.WriteLine(classAttribute.Name); // Output: Example Console.WriteLine(methodAttribute.Name); // Output: Method Example

4. 特性的常见用途
  • 标记和文档化:例如,[Obsolete][Serializable] 等特性,用于标记类或方法。

  • 自定义验证和授权:如 [Authorize] 特性用于身份验证。

  • 数据映射:比如在ORM框架(如Entity Framework)中使用特性来映射数据库表和字段。

  • 代码生成:某些框架或工具使用特性来自动生成代码。

二、C#中的反射(Reflection)

反射是指在运行时检查和操作类型、方法、属性、字段等的能力。反射可以用于获取类型信息、动态创建对象、调用方法、访问字段等。

1. 获取类型信息

反射提供了 Type 类来获取对象的类型信息。例如:

csharp

复制编辑

Type type = typeof(MyClass); // 获取类型信息 Console.WriteLine(type.FullName); // 输出类的完整名称

如果你有一个对象实例,也可以通过 .GetType() 获取其类型:

csharp

复制编辑

MyClass obj = new MyClass(); Type type = obj.GetType(); Console.WriteLine(type.FullName);

2. 获取和操作成员信息

可以使用反射获取类型的构造函数、方法、字段、属性等信息:

csharp

复制编辑

var methodInfo = type.GetMethod("MyMethod"); methodInfo.Invoke(obj, null); // 调用MyMethod

获取字段:

csharp

复制编辑

var fieldInfo = type.GetField("myField"); fieldInfo.SetValue(obj, 42); // 设置字段值 Console.WriteLine(fieldInfo.GetValue(obj)); // 获取字段值

获取属性:

csharp

复制编辑

var propertyInfo = type.GetProperty("MyProperty"); propertyInfo.SetValue(obj, "New Value"); Console.WriteLine(propertyInfo.GetValue(obj));

3. 动态创建实例

反射可以动态创建对象:

csharp

复制编辑

var constructor = type.GetConstructor(Type.EmptyTypes); var instance = constructor.Invoke(null);

4. 动态方法调用

通过反射可以动态调用方法,无论是实例方法还是静态方法:

csharp

复制编辑

var method = type.GetMethod("MyMethod"); method.Invoke(obj, new object[] { param1, param2 });

5. 使用反射获取特性

反射也可以用来获取与某个成员相关的特性:

csharp

复制编辑

var attributes = type.GetCustomAttributes(typeof(MyCustomAttribute), false); foreach (var attribute in attributes) { Console.WriteLine(((MyCustomAttribute)attribute).Name); }

三、特性与反射的结合

反射和特性通常是结合使用的。在实际应用中,特性可以用于标记代码的某些元数据,而反射则可用于在运行时读取这些信息。例如,在自定义的ORM框架中,可以通过特性来标记类和字段与数据库的映射关系,然后通过反射在运行时自动构建数据库查询。

例如,假设你有如下的特性:

csharp

复制编辑

[AttributeUsage(AttributeTargets.Property)] public class ColumnAttribute : Attribute { public string ColumnName { get; } public ColumnAttribute(string columnName) { ColumnName = columnName; } }

你可以用它标记类的属性:

csharp

复制编辑

public class Person { [Column("person_name")] public string Name { get; set; } [Column("person_age")] public int Age { get; set; } }

然后通过反射来读取特性并生成SQL查询:

csharp

复制编辑

Type type = typeof(Person); var properties = type.GetProperties(); foreach (var property in properties) { var columnAttribute = (ColumnAttribute)Attribute.GetCustomAttribute(property, typeof(ColumnAttribute)); if (columnAttribute != null) { Console.WriteLine($"Property: {property.Name}, Column: {columnAttribute.ColumnName}"); } }

四、反射的性能问题

反射的一个重要缺点是性能开销较大,特别是在频繁使用反射时。如果你的应用程序对性能要求非常高,尽量减少反射的使用,或考虑使用其他优化方式(如缓存反射信息)。

总结

  • 特性(Attributes):用于给代码元素(如类、方法、属性等)添加元数据,通常在运行时获取这些元数据。

  • 反射(Reflection):用于在运行时获取类型信息并动态操作对象,可以动态创建对象、调用方法、访问字段等。

  • 结合使用:通过反射获取和处理特性,能够让程序在运行时更加灵活、可扩展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92959.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92959.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL 语法详解

SQL 语法详解 引言 SQL(Structured Query Language)是一种用于数据库管理的标准语言,它允许用户进行数据的查询、更新、插入和删除等操作。SQL语法是数据库管理和编程的基础,本篇文章将详细介绍SQL的基本语法和常用操作&#xff0…

为什么 sim(3) 中的尺度 s 与旋转 R 相乘,而不是平移 t?

文章目录为什么 sim(3) 中的尺度 s 与旋转 R 相乘,而不是平移 t?1️⃣ sim(3) vs SE(3):结构对比与核心差异2️⃣ 为什么尺度 s 不乘在 t 上?🚫 数学破坏:🧭 几何解释:3️⃣ t 是“相…

如何为你的 Docker 容器设置代理网络

一文搞定!如何为你的 Docker 容器设置代理网络(及一个最常见的“坑”) 你是否遇到过这样的窘境:在你的服务器上,代理工具(比如 Clash, V2Ray)运行得好好的,浏览器也能科学上网,但一旦把应用放进 Docker 容器,它就瞬间“失联”,无法访问外部世界? 别担心,这是每个…

LeetCode Day3 -- 哈希表

目录 1. 啥是哈希表? 2. 啥时候用哈希表? 2.1 存在性检查 → 集合Set 2.2 键值映射 → 字典Dict 2.3 频率统计 → Dict or Counter 3. LeetCode 3.1 集合 (1)2215 找出两数组的不同 (2)1207 独一无…

三子棋装置(电赛24E题)K230/STM32全开源

三子棋装置(电赛24E题)K230/STM32全开源,后续有具体代码参数讲解,帮助大家移植k230代码import time, os, sysfrom media.sensor import * from media.display import * from media.media import *from machine import UART from m…

终端安全检测与防御

1. 终端安全风险主要问题:企业网络中80%的安全事件源于终端,终端成为黑客攻击的重要目标。攻击手段:勒索病毒:直接勒索用户。横向渗透:通过受控终端攻击内部服务器。僵尸网络危害:信息窃取、钓鱼网站引导、…

Video_AVI_Packet(2)

博主声明:内容来自网络,仅供参考,仅适用于浅了解,如有错误,自行甄别,由此引起的后果概不负责 Video_AVI_Packet(2)一、Video Picture Aspect Ratio 与 Active Format Aspect Ratio1.…

八月补丁星期二:微软修复 111 个漏洞

微软将在2025 年 8 月补丁星期二修复 111 个漏洞,这一数量与近期平均水平大致相同。 与上个月的情况类似,微软知道今天发布的漏洞中只有一个已被公开披露,但声称没有证据表明存在野外利用。同样,截至发布时,唯一的补丁…

《C++进阶之继承多态》【普通类/模板类的继承 + 父类子类的转换 + 继承的作用域 + 子类的默认成员函数】

【普通类/模板类的继承 父类&子类的转换 继承的作用域 子类的默认构造函数】目录前言:------------------------一、继承的定义和使用1. 什么使继承?2. 为什么要引入继承?3. 怎么使用继承?① 父类(基类&#xf…

Ubuntu22.04安装OBS Studio

OBS官网的最新的虽然支持Ubuntu系统,但是只支持最新的24.2版本的,而我的电脑上的Ubuntu的版本是22.04,所以在网上寻求解决办法,看到了这一片博客,作为参考来实现ubuntu22.04安装OBS,这里提示一下&#xff0…

Ansible 基本使用

Ansible 清单 静态主机清单 主机清单支持多种格式,例如ini、yaml、脚本等。 本次课程使用 ini 格式。 #创建主机清单[lykcontroller ~ 13:36:01]# vim inventory#vim添加controllernode1node2node3node4​#测试连接单个服务器[lykcontroller ~ 14:08:18]$ ansibl…

网络资源模板--基于Android Studio 实现的九寨沟App

目录 一、测试环境说明 二、项目简介 三、项目演示 四、部设计详情(部分) 首页 购票页面 五、项目源码 一、测试环境说明 电脑环境 Windows 11 编写语言 JAVA 开发软件 Android Studio (2020) 开发软件只要大于等于测试版本即可(近几年官网直接下载也…

系统架构设计师备考之架构设计实践知识

1.信息系统架构设计理论与实践1.1.基本概念信息系统架构定义目前关于信息系统架构较为权威的定义有: (1)信息系统架构是系统的结构,由软件元素、元素外部可见属性和元素间关系组成。 (2)信息系统架构是软件…

【IgH EtherCAT】如何利用 RTAI 提供的实时任务和调度机制来构建一个高精度、确定性的工业控制应用

SVG图展示了系统的分层架构:RTAI实时层:包含RT_TASK、信号量和定时器EtherCAT Master层:主站、域、从站配置和PDO映射EtherCAT网络层:与实际硬件设备(EL3162模拟输入、EL2004数字输出)通信关键特点&#xf…

7款热门智能电视文件管理器横向评测

7款智能电视文件管理器横向评测 在智能电视和电视盒子日益普及的今天,一款好用的文件管理器能让您的数字生活更加便捷。本文为您评测了7款广受欢迎的TV版文件管理器,助您找到最适合自己的工具。 1. ES文件浏览器TV版 ES文件浏览器是一款广受欢迎的多功能…

Python 类元编程(导入时和运行时比较)

导入时和运行时比较 为了正确地做元编程,你必须知道 Python 解释器什么时候计算各个代码 块。Python 程序员会区分“导入时”和“运行时”,不过这两个术语没有严 格的定义,而且二者之间存在着灰色地带。在导入时,解释器会从上到 下…

[git diff] 对比检查变更 | 提交前复审 | 版本回退

git diff git diff 是 Git 版本控制系统中用于比较文件差异的核心命令,可以显示工作目录、暂存区(Index)和仓库历史之间的变化。 通过对比不同版本或状态的文件内容,帮助开发者理解代码变更。 比较工作目录与暂存区 运行以下命令查…

【数据可视化-85】海底捞门店数据分析与可视化:Python + pyecharts打造炫酷暗黑主题大屏

🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

物联网之小白调试网关设备

小伙伴们,你们好呀!我是老寇!跟我一起学习调试网关设备 相信搞过物联网的朋友,对网关设备非常熟悉,本人以小白的视角,手把手教你调试网关设备! 工作中使用的是Ubuntu操作系统,因此&a…

Node.js特训专栏-实战进阶:22. Docker容器化部署

🔥 欢迎来到 Node.js 实战专栏!在这里,每一行代码都是解锁高性能应用的钥匙,让我们一起开启 Node.js 的奇妙开发之旅! Node.js 特训专栏主页 专栏内容规划详情 我将从Docker容器化部署的基础概念入手,介绍Node.js应用容器化的步骤,包括创建Dockerfile、构建镜像、运行…