什么是反射

发射是 .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. WordPress主题开发实例:获取当前分类的文章列表

    思路: 如果使用默认的wordpress的方法,调出来的数据就会被后台的显示个数所限制,而我们需要的是自由控制文章数和翻页,所以我使用WP_Query 获取当前分类的方法可以通过 get_query_ ...

  2. Scala:Functional Objects

    先上代码 class FunctionalObjects(var _x: Int, var _y: Int) { require(_x > 0) require(_y > 0) def t ...

  3. 机器学习数据集,主数据集不能通过,人脸数据集介绍,从r包中获取数据集,中国河流数据集

    机器学习数据集,主数据集不能通过,人脸数据集介绍,从r包中获取数据集,中国河流数据集   选自Microsoft www.tz365.Cn 作者:Lee Scott 机器之心编译 参与:李亚洲.吴攀. ...

  4. Netty重要概念介绍

    Netty重要概念介绍 Bootstrap Netty应用程序通过设置bootstrap(引导)类开始,该类提供了一个用于网络成配置的容器. 一种是用于客户端的Bootstrap 一种是用于服务端的S ...

  5. 转: 调整 Linux I/O 调度器优化系统性能

    转自:https://www.ibm.com/developerworks/cn/linux/l-lo-io-scheduler-optimize-performance/index.html 调整 ...

  6. 【jQuery Demo】图片瀑布流实现

    瀑布流就是像瀑布一样的网站——丰富的网站内容,特别是绚美的图片会让你流连忘返.你在浏览网站的时候只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你面前.瀑布流网站是新兴的一种网站模式——她的 ...

  7. SVN命令行更新代码

    命令列表 svn help查看帮助信息 Available subcommands: add auth blame (praise, annotate, ann) cat changelist (cl ...

  8. 分区工具parted的详解及常用分区使用方法【转】

    来源:http://blog.51cto.com/zhangmingqian/1068779 分区工具parted的详解及常用分区使用方法 一.         parted的用途及说明 概括使用说明 ...

  9. Gitbook 命令行工具

    1.Gitbook 简介 1.1 Gitbook GitBook 是一个基于 Node.js 开发的命令行工具,使用它可以很方便的管理电子书,GitBook 是目前最流行的开源书籍写作方案. 使用 G ...

  10. EF+LINQ事物处理

    在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作同一条数据的同一个字段的话, ...