什么是反射

发射是 .net framework 提供的一个帮助类库,用于读取和使用元数据。

用到的类:System.Reflection,System.Type。System.Type 类对于反射起着核心的作用。 当反射请求加载的类型时,公共语言运行时将为它创建一个 Type。 您可以使用 Type 对象的方法、字段、属性和嵌套类来查找有关该类型的所有信息。

反射优缺点

优点:

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

缺点:

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

反射的用途

  • 1、它允许在运行时查看特性(attribute)信息。
  • 2、它允许审查集合中的各种类型,以及实例化这些类型。
  • 3、它允许延迟绑定的方法和属性(property)。
  • 4、它允许在运行时创建新类型,然后使用这些类型执行一些任务。
  • 5、MVC的路由就是反射做的。访问的Global的时候,会加载一遍dll

查看元数据

1、获取当前实例的 System.Type 的两种方式

//使用对象 GetType()方法
Rectangle nc = new Rectangle();
Type type = nc.GetType(); //使用 C# typeof 运算符
Type type = typeof(Rectangle);

2、查看类中的成员

MemberInfo[] minfos = type.GetMembers();
foreach (var i in minfos)
{
Console.WriteLine("成员: {0}", i.Name);
}

3、查看类中的构造方法

ConstructorInfo[] ci = type.GetConstructors();
foreach (var i in ci)
{
Console.WriteLine("构造函数: {0}", i.Name);
}

4、查看类中的属性

PropertyInfo[] pis = type.GetProperties();
foreach (var i in pis)
{
Console.WriteLine("属性: {0}", i.Name);
}

5、查看类中的字段

FieldInfo[] fis = type.GetFields();
foreach (var i in fis)
{
Console.WriteLine("字段: {0}", i.Name);
}

6、用反射生成对象,并调用属性、方法和字段进行操作

object obj = Activator.CreateInstance(type);// 创建实例
FieldInfo fi = type.GetField("hight");// 取得hight字段
fi.SetValue(obj, );// 给hight字段赋值
PropertyInfo pi1 = type.GetProperty("length");// 取得length属性
pi1.SetValue(obj, , null);// 给length属性赋值
PropertyInfo pi2 = type.GetProperty("width");// 取得width属性
pi2.SetValue(obj, , null);// 给width属性赋值
MethodInfo mi = type.GetMethod("GetVolume");// 取得GetVolume方法
mi.Invoke(obj, null);// 调用GetVolume方法

7、查看类中的特性、

Object[] attributes = type.GetCustomAttributes(false);
foreach (var i in attributes)
{
DeBugInfo dbi = i as DeBugInfo;
if (null != dbi)
{
Console.WriteLine("Bug no: {0}, Message: {1}", dbi.BugNo, dbi.Message);
}
}

8、完整代码

using System;
using System.Reflection;
namespace ConsoleTest
{
// 一个自定义特性 BugFix 被赋给类及其成员
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)] public class DeBugInfo : System.Attribute
{
private int bugNo;
public string message; public DeBugInfo(int bg)
{
this.bugNo = bg;
} public int BugNo
{
get
{
return bugNo;
}
}
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
/// <summary>
/// 矩形
/// </summary>
[DeBugInfo(, Message = "Return type mismatch")]
[DeBugInfo(, Message = "Unused variable")]
public class Rectangle
{
public int hight = ;
public double length { get; set; }
public double width { get; set; }
public Rectangle()
{
}
public Rectangle(double l, double w)
{
length = l;
width = w;
}
// 计算面积
[DeBugInfo(, Message = "Return type mismatch")]
public void GetArea()
{
Console.WriteLine("面积: {0}", length * width);
}
//计算体积
[DeBugInfo()]
public void GetVolume()
{
Console.WriteLine("体积: {0}", length * width * hight);
}
} class ExecuteRectangle
{
public static void Main12()
{
//使用对象GetType()方法
//Rectangle nc = new Rectangle();
//Type type = nc.GetType(); //使用 C# typeof 运算符
Type type = typeof(Rectangle); // 获取 Rectangle 类的所有成员
Console.WriteLine("\n遍历 Rectangle 类的成员开始---------------");
MemberInfo[] minfos = type.GetMembers();
foreach (var i in minfos)
{
Console.WriteLine("成员: {0}", i.Name);
}
Console.WriteLine("-------------------结束-------------------"); // 获取 Rectangle 类的所有构造函数
Console.WriteLine("\n遍历 Rectangle 类的构造函数开始-----------");
ConstructorInfo[] ci = type.GetConstructors();
foreach (var i in ci)
{
Console.WriteLine("构造函数: {0}", i.Name);
}
Console.WriteLine("-------------------结束-------------------"); // 获取 Rectangle 类的所有属性
Console.WriteLine("\n遍历 Rectangle 类的属性开始---------------");
PropertyInfo[] pis = type.GetProperties();
foreach (var i in pis)
{
Console.WriteLine("属性: {0}", i.Name);
}
Console.WriteLine("-------------------结束-------------------"); // 获取 Rectangle 类的所有public字段
Console.WriteLine("\n遍历 Rectangle 类的字段开始---------------");
FieldInfo[] fis = type.GetFields();
foreach (var i in fis)
{
Console.WriteLine("字段: {0}", i.Name);
}
Console.WriteLine("-------------------结束-------------------"); //用反射生成对象,并调用属性、方法和字段进行操作
Console.WriteLine("\n用反射生成对象,并调用属性、方法和字段进行操作");
object obj = Activator.CreateInstance(type);// 创建实例
FieldInfo fi = type.GetField("hight");// 取得hight字段
fi.SetValue(obj, );// 给hight字段赋值
PropertyInfo pi1 = type.GetProperty("length");// 取得length属性
pi1.SetValue(obj, , null);// 给length属性赋值
PropertyInfo pi2 = type.GetProperty("width");// 取得width属性
pi2.SetValue(obj, , null);// 给width属性赋值
MethodInfo mi = type.GetMethod("GetVolume");// 取得GetVolume方法
mi.Invoke(obj, null);// 调用GetVolume方法
Console.WriteLine("-------------------结束-------------------"); // 遍历 Rectangle 类的特性
Console.WriteLine("\n遍历 Rectangle 类的特性开始---------------");
Object[] attributes = type.GetCustomAttributes(false);
foreach (var i in attributes)
{
DeBugInfo dbi = i as DeBugInfo;
if (null != dbi)
{
Console.WriteLine("Bug no: {0}, Message: {1}", dbi.BugNo, dbi.Message);
}
}
Console.WriteLine("-------------------结束-------------------"); // 遍历 Rectangle 类的方法上的特性(此处只遍历)
Console.WriteLine("\n遍历 Rectangle 类的方法上的特性开始-------");
MethodInfo[] m = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
foreach (var i in m )
{
foreach (Attribute a in i.GetCustomAttributes(true))
{
DeBugInfo dbi = a as DeBugInfo;
if (null != dbi)
{
Console.WriteLine("Bug no: {0}, for Method: {1}, Message: {2}", dbi.BugNo, i.Name, dbi.Message);
}
}
}
Console.WriteLine("-------------------结束-------------------"); Console.ReadLine();
}
}
} 反射的完整代码

反射的完整代码

运行结果:

System.Reflection.Assembly类

Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。

使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化。

//通过程序集名称返回Assembly对象
Assembly ass = Assembly.Load("ConsoleTest"); //通过DLL、EXE文件名称返回Assembly对象
Assembly ass = Assembly.LoadFrom("ConsoleTest.exe"); //通过Assembly获取程序集中类
Type t = ass.GetType("ConsoleTest.Rectangle"); //参数必须是类的全名 //通过Assembly获取程序集中所有的类
Type[] types = ass.GetTypes();

相关文章:http://www.runoob.com/csharp/csharp-reflection.html

https://www.cnblogs.com/Kare/p/4601436.html

http://www.cnblogs.com/yaozhenfa/p/CSharp_Reflection_1.html#3826975

C# 反射(Reflection)的更多相关文章

  1. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  2. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  3. [整理]C#反射(Reflection)详解

    本人理解: 装配件:Assembly(程序集) 晚绑定:后期绑定 MSDN:反射(C# 编程指南) -----------------原文如下-------- 1. 什么是反射2. 命名空间与装配件的 ...

  4. CSharpGL(43)环境映射(Environment Mapping)-天空盒(Skybox)反射(Reflection)和折射(Refraction)

    CSharpGL(43)环境映射(Environment Mapping)-天空盒(Skybox)反射(Reflection)和折射(Refraction) 开始 如图所示,本文围绕GLSL里的sam ...

  5. 代理(Proxy)和反射(Reflection)

    前面的话 ES5和ES6致力于为开发者提供JS已有却不可调用的功能.例如在ES5出现以前,JS环境中的对象包含许多不可枚举和不可写的属性,但开发者不能定义自己的不可枚举或不可写属性,于是ES5引入了O ...

  6. Golang 反射reflection

    反射reflection 反射可大大提高程序的灵活性,使得interface{}有更大的发挥余地 反射使用TypeOf和ValueOf函数从接口中获取目标对象信息 反射会将匿名字段作为独立字段(匿名字 ...

  7. C# 反射(Reflection)技术

    本文参考自C#反射(Reflection)详解,纯属学习笔记,加深记忆 在介绍反射前,先介绍一个重要的知识点         .Net应用程序是由程序集(Assembly).模块(Module).类型 ...

  8. C#反射(Reflection)详解

    1. 什么是反射2. 命名空间与装配件的关系3. 运行期得到类型信息有什么用4. 如何使用反射获取类型5. 如何根据类型来动态创建对象6. 如何获取方法以及动态调用方法7. 动态创建委托 1.什么是反 ...

  9. C# 反射Reflection——反射反射程序员的快乐

    一.什么是反射 反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata. 反射是无处不在的,MVC-Asp.Ne ...

  10. Laravel学习笔记之PHP反射(Reflection) (上)

    Laravel学习笔记之PHP反射(Reflection) (上) laravel php reflect 2.1k 次阅读  ·  读完需要 80 分钟 3 说明:Laravel中经常使用PHP的反 ...

随机推荐

  1. Markdown 语法手册 - 完整版(上)

    https://blog.csdn.net/witnessai1/article/details/52551362 1. 斜体和粗体 代码: *斜体*或_斜体_ **粗体** ***加粗斜体*** ~ ...

  2. XMPP接受发送消息

    在现阶段的通信服务中,各种标准都有,因此会出现无法实现相互连通,而XMPP(Extensible Message and presence Protocol)协议的出现,实现了整个及时通信服务协议的互 ...

  3. 设置Linux交换分区

    Linux下可以创建两种类型的交换空间,一种是swap分区,一种是swap文件.前者适合有空闲的分区可以使用,后者适合于没有空的硬盘分区,硬盘的空间都已经分配完毕.例如:安装redhat的时候,你可以 ...

  4. 【CLR】解析AppDomain

    目录结构: contents structure [+] 什么是AppDomain 跨越AppDomain边界访问对象 按引用封送(Marshal-by-Reference) 按值封送(Marshal ...

  5. EasyUI tab问题记录

    1.  关闭当前tab 此代码放在  布局页中,然后所有的页面都可以随时关闭tab了,适当的根据你的项目,更改下js <script> function closetab(subtitle ...

  6. 12C -- 创建RMAN备份用户

    1.NON-CDB环境 SQL> create user backup_admin identified by backup_admin default tablespace users; SQ ...

  7. sonarqube 自动代码审查

    1.docker 拉取sonarqube docker pull sonarqube 2.启动docker docker run -d --name sonarqube -p 9000:9000 so ...

  8. Shell函数的7种用法介绍

    1. 在shell文件内部定义函数并引用: 复制代码代码如下: [~/shell/function]# cat factorial.sh #!/bin/bashfunction factorial{f ...

  9. 为OLED屏添加GUI支持6:进度条控件

    为OLED屏添加GUI支持6:进度条控件 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN10 开发环境:MDK5.13 MCU:S ...

  10. 菜鸟教程之工具使用(八)——EGit禁止自动转换回车换行符

    众所周知,Windows和Linux系统的回车换行是不一样的.想要进一步了解它们的可以阅读下面的介绍,不感兴趣的可以直接跳过. 产生背景 关于“回车”(carriage return)和“换行”(li ...