C#秘密武器之反射——基础篇
先来一段有用的反射代码
![](/assets/blank.gif)
![](/assets/blank.gif)
namespace Calculator { public interface Iwel { String Print(); } } namespace Calculator { public class Arithmetic:Iwel { /// <summary> /// 没有带参数的构造函数 /// </summary> public Arithmetic() {} public Arithmetic(int num1, int num2) { _num1 = num1; _num2 = num2; } private int _num1; public int Num1 { get { return _num1; } set { _num1 = value; } } private int _num2; public int Num2 { get { return _num2; } set { _num2 = value; } } public String Add(int num1, int num2) { Console.WriteLine("{0}+{1}={2}", num1, num2, num1 + num2); return "Add(int num1,int num2)方法是一个公有的带参数的方法"; } private string Add() { return "Add()方法是一个私有的不传参数的方法"; } private void Subtration(int num1, int num2) { Console.WriteLine("{0}-{1}={2}+Subtration(int num1,int num2)" + "方法是一个私有的带有参数的方法 ",num1,num2,num1-num2); } public static void Multiplication(int num1, int num2) { Console.WriteLine("{0}*{1}={2} Multiplication(int num1,int num2)"+"是一个公有的带参数的静态方法",num1,num2,num1+num2); } private static void Multiplication() { Console.WriteLine("Multiplication()是一个公有的带参数的静态方法"); } public String Writ() { return "Writ() 是一个公有的不带参数的方法"; } #region Iwel 成员 public string Print() { return "欢迎您使用接口!"; } #endregion } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace BassLib { class Program { delegate void TestDelegate(int num1, int num2); static void Main(string[] args) { Assembly assembly = Assembly.Load("Calculator");//加载程序集 Console.WriteLine("得到Calculator.dll中的所有类"); Console.WriteLine("***********************************"); foreach (Type myType in assembly.GetTypes()) { //得到Calculator.dll中所有的类 Console.WriteLine(myType.Name + "是Calculator命中空间下的类"); } Console.WriteLine(" +++++++++++++++++++++++++++++++++++++"); Console.WriteLine("得到Calculator.dll中的模块集"); Module[] modules = assembly.GetModules();//得到Calculator.dll中的模块集合 foreach (Module module in modules) { Console.WriteLine(module.Name + "是Calculator中的一个模块 "); } Console.WriteLine("*********************************************"); Console.WriteLine(""); Type type = typeof(Calculator.Arithmetic);//得到具体的类型 Console.WriteLine("具体的类型是" + type.Name); Console.WriteLine(" {0}是不是public类型:{1}", type, type.IsPublic); Console.WriteLine("{0}是不是private类型:{1}", type, type.IsNotPublic); Console.WriteLine("*********************************************"); Console.WriteLine(""); PropertyInfo[] memberInfo = type.GetProperties();//得到类中的属性 foreach (PropertyInfo var in memberInfo) { Console.WriteLine(type + "类的属性有" + var.Name); } Console.WriteLine("**********************************************"); Console.WriteLine(""); Type[] t = type.GetInterfaces();//得到接口 foreach (Type var in t) { Console.WriteLine(var.Name + "是Calculator.dll中的接口"); } Console.WriteLine("*****************************************"); Console.WriteLine(""); Console.WriteLine("方法的返回类型,方法传参的类型"); //查找私有的方法 MethodInfo[] method = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); foreach (MemberInfo var in method) { Console.WriteLine("私有方法: 方法名 ={0} 方法的信息={1}", var.Name, var); } //查找公有方法 MethodInfo[] methodpublic = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo var in methodpublic) { Console.WriteLine("公有方法:方法名={0} 方法的信息={1}", var.Name, var); } //查找公有的静态方法 MethodInfo[] mathodstatic = type.GetMethods(BindingFlags.Public | BindingFlags.Static); foreach (MethodInfo var in mathodstatic) { Console.WriteLine("公有静态方法: 方法名={0} 方法的信息 ={1}", var.Name, var); } //查找私有静态方法 MethodInfo[] methodprivartstatic = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static); foreach (MethodInfo var in methodprivartstatic) { Console.WriteLine("私有静态方法: 方法名={0} 方法的信息={1}", var.Name, var); } Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++"); Console.WriteLine("这是一个构造方法的形式 "); ConstructorInfo[] con = type.GetConstructors();//获得构造函数的形式 foreach (ConstructorInfo var in con) { Console.WriteLine(var); } Console.WriteLine("_________________________________"); object obj = Activator.CreateInstance(type, null);//创建了一个不带参数的实例 //公有非静态带参数和返回参数的方法的调用它 MethodInfo men1 = type.GetMethod("Add"); Console.WriteLine("调用{0}方法 ", men1); object[] nums1 = { 5, 4 };//参数 Console.WriteLine(men1.Invoke(obj, nums1)); Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); //私有的非静态方法的调用 MethodInfo men2 = type.GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic); Console.WriteLine(men2.Invoke(obj, null)); Console.WriteLine("**********************************"); //公有的静态带参数的方法的调用 MethodInfo men3 = type.GetMethod("Multiplication", BindingFlags.Public | BindingFlags.Static); object[] nums2 = { 5, 6 }; men3.Invoke(null, nums2); Console.WriteLine("*****************"); //私有的静态的 MethodInfo men4 = type.GetMethod("Multiplication", BindingFlags.NonPublic | BindingFlags.Static); men4.Invoke(null, null); Console.WriteLine("************************"); //动态创建一个委托 Console.WriteLine("动态创建委托"); TestDelegate dele = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), obj, "Subtration"); dele(9, 3); } } }
View Code
反射的几种基本类型
1、System.Reflection.Assembly类
通过Assembly可以动态加载程序集,并查看程序集的内部信息,其中最常用的就是Load()这个方法。
Assembly assembly=Assembly.Load("MyAssembly");
利用Assembly的object CreateInstance(string) 方法可以反射创建一个对象,参数0为类名。
2、System.Type类
Type是最常用到的类,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。一般有三个常用的方法可得到Type对象。
利用typeof() 得到Type对象
Type type=typeof(Example);
利用System.Object.GetType() 得到Type对象
Example example=new Example();
Type type=example.GetType();
利用System.Type.GetType() 得到Type对象
Type type=Type.GetType("MyAssembly.Example",false,true);
注意参数0是类名,参数1表示若找不到对应类时是否抛出异常,参数1表示类名是否区分大小写
例子:
我们最常见的是利用反射与Activator结合来创建对象:
Assembly assembly= Assembly.Load("MyAssembly"); Type type=assembly.GetType("Example"); object obj=Activator.CreateInstance(type);
3、反射方法
1.通过 System.Reflection.MethodInfo能查找到类里面的方法
代码:
Type type=typeof(Example); MethodInfo[] listMethodInfo=type.GetMethods(); foreach(MethodInfo methodInfo in listMethodInfo) Cosole.WriteLine("Method name is "+methodInfo.Name);
2.我们也能通过反射方法执行类里面的方法
代码:
Assembly assembly= Assembly.Load("MyAssembly"); Type type=assembly.GetType("Example"); object obj=Activator.CreateInstance(type); MethodInfo methodInfo=type.GetMethod("Hello World"); //根据方法名获取MethodInfo对象 methodInfo.Invoke(obj,null); //参数1类型为object[],代表Hello World方法的对应参数,输入值为null代表没有参数
4、反射属性
1.通过 System.Reflection.PropertyInfo 能查找到类里面的属性
常用的方法有GetValue(object,object[]) 获取属性值和 SetValue(object,object,object[]) 设置属性值
代码:
Type type=typeof(Example); PropertyInfo[] listPropertyInfo=type.GetProperties(); foreach(PropertyInfo propertyInfo in listPropertyInfo) Cosole.WriteLine("Property name is "+ propertyInfo.Name);
2.我们也可以通过以下方法设置或者获取一个对象的属性值
代码:
Assembly assembly=Assembly.Load("MyAssembly"); Type type=assembly.GetType("Example"); object obj=Activator.CreateInstance(type); PropertyInfo propertyInfo=obj.GetProperty("Name"); //获取Name属性对象 var name=propertyInfo.GetValue(obj,null); //获取Name属性的值 PropertyInfo propertyInfo2=obj.GetProperty("Age"); //获取Age属性对象 propertyInfo2.SetValue(obj,34,null); //把Age属性设置为34
5、反射字段
通过 System.Reflection.FieldInfo 能查找到类里面的字段
它包括有两个常用方法SetValue(object ,object )和GetValue(object) 因为使用方法与反射属性非常相似,在此不再多作介绍
6、反射特性
通过System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一个类里面的特性,以下例子可以反射出一个类的所有特性
代码:
Type type=typeof("Example"); object[] typeAttributes=type.GetCustomAttributes(false); //获取Example类的特性 foreach(object attribute in typeAttributes) Console.WriteLine("Attributes description is "+attribute.ToString());
通过下面例子,可以获取Example类Name属性的所有特性
代码:
public class Example{[DataMemberAttribute]publics string Name{get;set;}..................}Type type = typeof(Example); PropertyInfo propertyInfo=type.GetProperty("Name"); //获取Example类的Name属性foreach (object attribute in propertyInfo.GetCustomAttributes(false)) //遍历Name属性的所有特性Console.WriteLine(“Property attribute: "+attribute.ToString());
7、反射成员
我们先考虑一下对于一个类型Type,可能会包含什么类型,常见的有字段、属性、方法、构造函数、接口、嵌套类型等。MemberInfo 类代表着 Type的成员类型,值得注意的是Type类本身又继承自MemberInfo类,理解起来并不困难,因为一个类型经常也是另一类型的成员。Type类提供 GetMembers()、GetMember()、FindMember()等方法用于获取某个成员类型。
我们再添加一个方法 MemberExplore(),来查看一个类型的所有成员类型。
namespace Demo{
class SimpleExplore
{
static void Main(string[] args)
{
MemberExplore(typeof(DemoClass));
}
public static void MemberExplore(Type t)
{
StringBuilder sb = new StringBuilder();
MemberInfo[] memberInfo = t.GetMembers();
sb.Append("查看类型 " + t.Name + "的成员信息:\n");
foreach (MemberInfo mi in memberInfo)
{
sb.Append("成员:" + mi.ToString().PadRight(40) + " 类型: " + mi.MemberType + "\n");
}
Console.WriteLine(sb.ToString());
}
}
}
产生的输出如下:
我们使用了GetMembers()方法获取了成员信息的一个数组,然后遍历了数组,打印了成员的名称和类型。如同我们所知道的:Name属性在编译后成为了get_Name()和set_Name()两个独立的方法;myEvent事件的注册(+=)和取消注册(-=)分别成为了add_myEvent()和remove_myEvent方法。同时,我们发现私有(private)字段name 没有被打印出来,另外,基类System.Object的成员GetType()和Equals()也被打印了出来。
有的时候,我们可能不希望查看基类的成员,也可能希望查看私有的成员,此时可以使用GetMembers()的重载方法,传入BindingFlags 位标记参数来完成。BindingFlags位标记对如何获取成员的方式进行控制(也可以控制如何创建对象实例,后面会说明)。对于本例,如果我们想获取所有的公有、私有、静态、实例成员,那么只需要这样修改GetMembers()方法就可以了。
public static void MemberExplore(Type t)
{
StringBuilder sb = new StringBuilder();
//MemberInfo[] memberInfo = t.GetMembers();
MemberInfo[] memberInfo = t.GetMembers(BindingFlags.Public | BindingFlags.Static
| BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
sb.Append("查看类型 " + t.Name + "的成员信息:\n");
foreach (MemberInfo mi in memberInfo)
{
sb.Append("成员:" + mi.ToString().PadRight(40) + " 类型: " + mi.MemberType + "\n");
}
Console.WriteLine(sb.ToString());
}
此时的输出如下:
可以看到,继承自基类 System.Object 的方法都被过滤掉了,同时,打印出了私有的 name, myEvent 等字段。
现在如果我们想要获取所有的方法(Method),那么我们可以使用 Type类的FindMembers()方法:
public static void MemberExplore(Type t)
{
StringBuilder sb = new StringBuilder();
//MemberInfo[] memberInfo = t.GetMembers();
//MemberInfo[] memberInfo = t.GetMembers(BindingFlags.Public | BindingFlags.Static
// | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
MemberInfo[] memberInfo = t.FindMembers(MemberTypes.Method, // 说明查找的成员类型为 Method
BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic
| BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.FilterName, "*");
sb.Append("查看类型 " + t.Name + "的成员信息:\n");
foreach (MemberInfo mi in memberInfo)
{
sb.Append("成员:" + mi.ToString().PadRight(40) + " 类型: " + mi.MemberType + "\n");
}
Console.WriteLine(sb.ToString());
}
Type.FilterName 返回一个MemberFilter类型的委托,它说明按照方法名称进行过滤,最后一个参数“*”,说明返回所有名称(如果使用“Get*”,则会返回所有以Get开头的方法)。
现在的输出如下:
MemberInfo 类有两个属性值得注意,一个是DeclaringType,一个是 ReflectedType,返回的都是Type类型。DeclaredType 返回的是声明该成员的类型。比如说,回顾我们之前的一段代码:
MemberInfo[] members = typeof(DemoClass).GetMembers();
它将返回所有的公有成员,包括继承自基类的Equals()等方法,对于Equals()方法来说,它的 DeclaringType 返回的是相当于 typeof(Object) 的类型实例,因为它是在 System.Object中被定义的;而它的ReflectedType 返回的则是相当于 typeof(DemoClass) 类型实例,因为它是通过 DemoClass 的类型实例被获取的。
转载于:https://www.cnblogs.com/WeiGe/p/4202626.html
C#秘密武器之反射——基础篇相关推荐
- 互联网的秘密武器-标签体系流程篇 by彭文华
这是彭文华的第164篇原创 今天跟大家聊聊标签体系. 其实网上关于如何建标签体系的文章非常多,因为这本就是互联网企业必备的秘密武器啊,同时也是数据分析最常用的方式方法. 打标签这个事情,其实就是人类& ...
- 穿越Java - 基础篇 第十章 反向探知 - 反射 | 第1节 反射概述
主题:反射概述 开发环境 更多干货 定义: 作用: 理解: 总结: 开发环境 基于:IntelliJ IDEA.Maven构建工具.JDK1.8.SpringBoot 2.3.4 .Spring4.3 ...
- 大模型高效开发的秘密武器——大模型低参微调套件MindSpore PET篇
人工智能进入"大模型时代".大模型具备更强泛化能力,在各垂直领域落地时,只需要进行参数微调,就可以适配多个场景.因此,发展大模型已成为产学研各界共识. 在大模型开发方面,昇腾推出了 ...
- 反射第一篇,学习Java的反射基础
反射基础 什么是反射? 反射的使用 介绍:类对象 获取类对象 类对象的方法简介 使用:利用反射创建对象 例 调用特定构造方法 使用:获取成员变量并修改 例 使用:获取成员方法并调用 例 调用特定方法 ...
- 吐血整理:手拿几个大厂offer的秘密武器!
怎样才能拿到大厂的offer?没有掌握绝对的技术,那么就要不断的学习. 如何拿下阿里等大厂的offer呢,今天分享一个秘密武器,资深架构师整理的Java核心知识点,面试时面试官必问的知识点,篇章包括了 ...
- 吐血整理:手拿几个大厂offer的秘密武器!
怎样才能拿到大厂的offer?没有掌握绝对的技术,那么就要不断的学习. 如何拿下阿里等大厂的offer呢,今天分享一个秘密武器,资深架构师整理的Java核心知识点,面试时面试官必问的知识点,篇章包括了 ...
- 吐血整理:手拿几个大厂 Offer 的秘密武器!
怎样才能拿到大厂的offer?没有掌握绝对的技术,那么就要不断的学习. 如何拿下阿里等大厂的offer呢,今天分享一个秘密武器,资深架构师整理的Java核心知识点,面试时面试官必问的知识点,篇章包括了 ...
- 一些解密必备知识(2)- 基础篇03|解密系列
一些解密必备知识(2)- 基础篇03 让编程改变世界 Change the world by program 软件安全是信息安全领域的重要内容,本系列视频教程将涉及到软件相关的加密.解密.逆向分析 ...
- SpringBoot2基础篇
目录 前言 从今天开始进入微服务阶段 一. HelloWorld 1.1.什么是SpringBoot 1.3.微服务架构 二.第一个SpringBoot程序 2.1.环境配置 2.2.创建基础项目说明 ...
最新文章
- airflow sql_alchemy_conn mysql_airflow的安装和使用 - 完全版
- 字节跳动内部 MySQL 学习笔记火了,完整版开放下载!
- 同事今天早上拍的几幅雪后的照片。传上来大家看看。
- 没有维护在库存管理中用于工厂1112的参数
- 使用Eclipse连接SAP Netweaver系统遇到的错误消息和解决办法
- 如何禁止使用bottomsheetdialogfragment拖动?
- aspcms模板转php,aspcms转换zzzcms,aspcms迁移数据,aspcms替换模板,aspcms模板转换-下载-zzzcms官网-开源免费建站系统...
- POJ-2078 Matrix,暴力枚举!
- 洛谷P3768 简单的数学题
- 京东联盟PHP接口源码
- 清华大学出来的工资有多高?| 文末送书
- linux蜂鸣器驱动指令,Linux 设备驱动简析—PC蜂鸣器驱动
- 京东,想说爱你,并不容易!
- Linux系统安全基础
- 10 场年薪 60W 的 DBA 面试,被问到最多的 10 道题
- 2021/7/8——集训Day.3
- 科罗拉多大学波尔得分校计算机科学,科罗拉多大学波尔得分校副教授Dan Zhang:基于线性规划的近似动态规划方面的一些最新成果...
- ccs一次替换一个多出使用的变量
- PMP|研发项目管理之问题及改进方法
- html让图片一直旋转,css如何设置不停旋转的图片?
热门文章
- C# DateTime ToString
- [react] 举例说明在react中怎么使用样式
- [react] 怎样动态导入组件?
- 前端学习(3299):自定义hook
- [html] websocket和http有什么区别?
- [vue] 说说你对SPA单页面的理解,它的优缺点分别是什么?
- “约见”面试官系列之常见面试题之第八十篇之css常见属性(建议收藏)
- 前端学习(1956)vue之电商管理系统电商系统之添加代码到仓库中
- 前端学习(799):根据位置返回字符
- 61setproperty对象