C# 反射 (Reflection) 的常用功能

news2024/11/17 7:50:40

目录

一、概述

二、实例化类

三、反射赋值

四、获取字段值

五、获取字段名

六、获取字段类型

七、调用方法

结束


一、概述

反射指程序可以访问、检测和修改它本身状态或行为的一种能力。

程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。

您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。


优点:

1、反射提高了程序的灵活性和扩展性。
2、降低耦合性,提高自适应能力。
3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。


缺点:

1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。


反射(Reflection)有下列用途:

它允许在运行时查看特性(attribute)信息。
它允许审查集合中的各种类型,以及实例化这些类型。
它允许延迟绑定的方法和属性(property)。
它允许在运行时创建新类型,然后使用这些类型执行一些任务。

二、实例化类

要想使用反射来实例化一个类,可以使用 Activator.CreateInstance 方法,但实际上,C# 的反射性能要比 new 差很多,所以在一般情况下,不推荐使用反射,但是也不代表反射不能使用,在很多项目中,反射用到的频率也是很高的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            object obj = Activator.CreateInstance(type);
            MyClass myClass = (MyClass)obj;
            Console.WriteLine("年龄:{0}", myClass.Age);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age { get; set; } = 12;
    }
}

运行:

 

三、反射赋值

1.字段类型

可以使用 FieldInfo.SetValue 来给字段赋值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            object obj = Activator.CreateInstance(type);

            FieldInfo field = type.GetField("Age");
            if (field != null)
                field.SetValue(obj, 42);

            MyClass myClass = (MyClass)obj;
            Console.WriteLine("年龄:{0}", myClass.Age);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age = 12;
    }
}

运行:

2.属性类型

根据上一节的代码可以看到,我把 Age 这个字段的属性去掉了,如果字段是一个属性, 调用 type.GetField("字段名") 方法返回的是 null。

下面是介绍如何给属性赋值:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            object obj = Activator.CreateInstance(type);
            PropertyInfo property = type.GetProperty("UserName");
            property.SetValue(obj, "李四");
            MyClass myClass = (MyClass)obj;
            Console.WriteLine("用户名:{0}", myClass.UserName);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age = 12;

        public string UserName { get; set; } = "张三";
    }
}

运行:

 

四、获取字段值

获取字段的值,只需要拿到当前类的实体对象就好了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            object obj = Activator.CreateInstance(type);
        
            MyClass myClass = (MyClass)obj;
            Console.WriteLine("年龄:{0}", myClass.Age);
            Console.WriteLine("用户名:{0}", myClass.UserName);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age = 12;

        public string UserName { get; set; } = "张三";
    }
}

运行:

 

五、获取字段名

1.字段类型

可以使用下面的方法来获取所有的字段名,但这种写法并不能获取属性的字段名

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                Console.WriteLine(field.Name);
            }

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age = 12;

        public string UserName { get; set; } = "张三";
    }
}

运行:

2.属性类型

代码大致差不多,区别在于,普通的字段使用 GetFields ,属性使用  GetProperties

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo property in properties)
            {
                Console.WriteLine(property.Name);
            }

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age = 12;

        public string UserName { get; set; } = "张三";
    }
}

运行:

 

六、获取字段类型

1.字段类型

可以使用 FieldInfo.FieldType 来获取字段的类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            FieldInfo field = type.GetField("Age");
            Type fieldType = field.FieldType;
            Console.WriteLine(fieldType);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age = 12;
        public string UserName { get; set; } = "张三";
    }
}

运行:

 

2.属性类型

可以使用 PropertyInfo.GetProperty 方法来获取属性的类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            PropertyInfo property = type.GetProperty("UserName");
            Type propertyType = property.PropertyType;
            Console.WriteLine(propertyType);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public int Age = 12;
        public string UserName { get; set; } = "张三";
    }
}

运行:

 

七、调用方法

可以使用 MethodInfo.Invoke 来调用方法

1.有参数

在这里,参数用的是一个数组,假设参数有两个,那么你在数组中也要加两个对应类型的值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            object obj = Activator.CreateInstance(type);
            MethodInfo method = type.GetMethod("Test");
            object[] parameters = new object[] { "老王" };
            string result = (string)method.Invoke(obj, parameters);
            Console.WriteLine("返回值 {0}" , result);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public string Test(string name)
        {
            return "你的名字:" + name;
        }
    }
}

运行:

 

2.无参数

假设方法无参数的时候,传值传空就好了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type type = typeof(MyClass);
            object obj = Activator.CreateInstance(type);
            MethodInfo method = type.GetMethod("SayHi");
            method.Invoke(obj, null);

            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public void SayHi()
        {
            Console.WriteLine("你好");
        }
    }
}

运行:

 

结束

如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言,谢谢!

end

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

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

相关文章

华为认证 | HCIE-Datacom 考试大纲

01 HCIE-Datacom考试概述 02 HCIE-Datacom考试内容 HCIE-Datacom V1.0 考试覆盖数据通信领域:路由交换高阶技术、企业网络架构全景、园区网络典型架构与技术、华为CloudCampus解决方案设计与部署、广域互联网络典型架构与技术、华为SD-WAN解决方案设计与部署、广域…

人机接口回路原理(四)

五、硬件时钟电路 接口插件设置了一个硬件时钟电路,由一片MC146818时钟芯片及辅助元器件组成,如图1-35所示。 MC146818芯片是智能式硬件时钟,其内部由电子时钟和存储器两部分组成。可计年、月、日、时、分、秒、星期;能…

时间序列中的无监督表示学习

自监督学习中,有一个常用的方法是对比学习; 2.  时间序列的表示学习 1.1 采用对比学习的方式 Time-series representation learning via temporal and contextual contrasting(IJCAI’21) 本文采用对比学习的方式进行时间序列表示学习。首先对于同一…

告别原始 UI 样式,拥抱 Fluent Design 风格 PyQt/PySide 组件库

简介 这是一个使用 PyQt/PySide 编写的 Fluent Design 风格的组件库,支持亮暗主题无缝切换和自定义主题色,搭配 QtDesigner 可以快速开发美观的界面。github 仓库地址为 https://github.com/zhiyiYo/PyQt-Fluent-Widgets ,演示视频可以在哔哩…

夏至后,这些农事活动要注意管理

夏至过后,温度会进一步攀登,较高的气温和光照会让夏作物生长更加旺盛。接下来就让我们看看在这些夏作物在种植时都需要注意哪些方面吧! 一、蔬菜管理 夏白菜、夏甘蓝、夏菜花都是在6月下旬开始育早熟的菜花苗,秋大棚中的芹菜也是…

超强总结,性能测试实战(购物业务板块)真实压测场景...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 购物网站购物流程…

人工智能(pytorch)搭建模型13-pytorch搭建RBM(受限玻尔兹曼机)模型,调通模型的训练与测试

大家好,我是微学AI,今天给大家介绍一下人工智能(pytorch)搭建模型13-pytorch搭建RBM(受限玻尔兹曼机)模型,调通模型的训练与测试。RBM(受限玻尔兹曼机)可以在没有人工标注的情况下对数据进行学习。其原理类似于我们人类学习的过程&#xff0c…

Redis简单动态字符串SDS

目录 前言 一.SDS定义 二.SDS与C字符串的区别 2.1 常数复杂度获取字符串的长度 2.2 杜绝缓冲区溢出 2.3 减少修改字符串时带来的内存重分配次数 2.3.1 空间预分配 2.3.2 惰性空间释放 2.4 二进制安全 2.5 兼容部分C字符串函数 2.6 总结 三.SDS缺点 前言 Redis没有直接使用C语…

gRPC教程与应用

gRPC是是谷歌一个开源的跨语言的RPC框架,面向移动和 HTTP/2 设计。 grpc中文网 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。 gRPC 也是基于以下理念&#xff1…

python3+requests+unittest接口自动化测试

1.环境准备 python3 pycharm编辑器 2.框架目录展示 (该套代码只是简单入门,有兴趣的可以不断后期完善) (1)run.py主运行文件,运行之后可以生成相应的测试报告,并以邮件形式发送;…

【C++进阶】红黑树实现

文章目录 红黑树的概念红黑树的性质红黑树节点的定义红黑树结构红黑树的插入1.按照二叉搜索的树规则插入新节点2.进行旋转和变色源码 红黑树的验证中序遍历判断是否满足二叉搜索树判断是否满足红黑树 完整源码 红黑树的概念 红黑树,是一种二叉搜索树,但…

基于spss的多元统计分析 之 单/双因素方差分析 多元回归分析(1/8)

实验目的: 1.掌握单样本t检验、两样本t检验、配对样本t检验、单因素方差分析、多元回归分析的基本原理; 2.熟悉掌握SPSS软件或者R软件关于单因素、多因素方差分析、多元回归分析的基本操作; 3.利用实验指导…

2.3C++保护成员

C 保护成员 在C中,可以使用保护成员 protected,来提高代码的安全性。 我用大白话解释一下什么是保护成员:说白了就是为了防止其他类直接访问或修改其成员加的一个措施。 目的是保护,成员的私有性和可见性。 C 类的保护 可以为…

web 语音通话 jssip

先把封装好的地址安上(非本人封装):webrtc-webphone: 基于JsSIP开发的webrtc软电话 jssip中文文档:jssip中文开发文档(完整版) - 简书 jssip使用文档:(我没有运行过,但…

Nginx服务器,在window系统中的使用(前端,nginx的应用)

简介:Nginx是一个轻量级、高性能的HTTP和反向代理web服务器,且支持电子邮件(IMAP/POP3)代理服务,特点是占用内存少,并发能力强,给我们来了很多的便利,国内大部分网站都有使用nginx&a…

18款奔驰S350升级后排座椅记忆功能,提升您乘坐舒适性

带有记忆功能的座椅可以存储三个的座椅设置以及行车电脑中的舒适性设置。只要按一下按钮就可以跳到记忆模式,让座椅回到上一次设置。

使用 BigQuery Omni,发现跨云地理空间分析的优势

【本文由 Cloud Ace 整理发布。Cloud Ace 是谷歌云全球战略合作伙伴,拥有 300 多名工程师,也是谷歌最高级别合作伙伴,多次获得 Google Cloud 合作伙伴奖。作为谷歌托管服务商,我们提供谷歌云、谷歌地图、谷歌办公套件、谷歌云认证…

第十章详解synchronized锁升级

文章目录 升级的流程为什么要引入锁升级这套流程多线程访问情况具体流程 轻量级锁如何使用CAS实现轻量级锁CAS加锁成功CAS加锁失败CAS进行解锁 总结何时变为重量级锁 锁膨胀自旋优化 偏向锁主要作用偏向状态测试撤销偏向锁 撤销 - 调用对象 hashCode撤销 - 其它线程使用对象撤销…

js:codemirror实现在线代码编辑器代码高亮显示

CodeMirror is a versatile text editor implemented in JavaScript for the browser. It is specialized for editing code, and comes with a number of language modes and addons that implement more advanced editing functionality. 译文:CodeMirror是一个多…

第二章:软件工程师必备的网络基础

目录 一、网线的制作 二、集线器、交换机介绍 三、路由器的配置 一、网线的制作 1.1、水晶头 ​​​ 1.2、网线钳 1.3、网线的标准 T568A标准(交叉线): 适用链接场合:电脑-电脑、交换机-交换机、集线器-集线器 接线顺序&…