什么是反射

发射是 .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. PKCS 15 个标准

    PKCS 全称是 Public-Key Cryptography Standards ,是由 RSA 实验室与其它安全系统开发商为促进公钥密码的发展而制订的一系列标准. 可以到官网上看看 What i ...

  2. [Canvas]飞机飞越河谷(背景向下平滑移动)

    请点击此处下载代码并用Chrome浏览器打开观看. 图例: 代码: <!DOCTYPE html> <html lang="utf-8"> <meta ...

  3. SQL与MySQL基本

    一:概念辨析 数据库(database):是一种保存有组织的数据的容器. 数据库软件(DBMS):使用DBMS操作数据库.访问数据库. SQL:结构化查询语言,专门用来与数据库通信的语言.几乎所有DB ...

  4. gcc/g++ disable warnings in particular include files

    当在编译一个大项目的时候,你想打开所有的Warning,但是打开后发现一堆公共库文件都出现了warning报错.此时如果你想忽略公共库头文件中的warning报错,只需要在编译的时候,将公共库头文件的 ...

  5. 详解C#特性和反射(一)

    使用特性(Attribute)可以将描述程序集的信息和描述程序集中任何类型和成员的信息添加到程序集的元数据和IL代码中,程序可以在运行时通过反射获取到这些信息: 一.通过直接或间接的继承自抽象类Sys ...

  6. MySQL 的主从原理和复制过程简述

    一.MySQL 复制的基本过程如下:1. Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容; 2. Master 接收到来自 Slav ...

  7. C# 版本的24点实现

    C# 版本的24点实现. 已经实现基本功能,可以正确的算 3, 3, 8, 8 这类组合. 稍加修改就可以支持任意数目的操作数和操作符组合形成的四则运算表达式,不限于24点. 代码还比较简单粗糙,晚一 ...

  8. 在GitHub中下载的项目,如何运行

    1.查看说明文档README-CN.md 2.大概流程 1.安装依赖 cnpm install 2.启动服务 npm run dev

  9. vue使用node的入门

    1.安装cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org 验证是否安装 cnpm -v 2.安装vue cnpm ...

  10. jsonp的工作原理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...