反射原理是什么

反射到底有什么用?

以前,假设我们要不借助任何类库直接解析Json协议的东西,比如{“a”:"A","b":"B","c":"C"},并且我们需要将他们赋给一个与之对应的实体类。那么我们需要写出如下的代码来解析

//这只是一段伪代码
while(str.Length!=0){//在一个大的while里面遍历整个字符串
//这里省去解析的函数
//用判断读到的名称,然后对应相应的属性进行初始化。
    if(name=="a"){
       SetA(value);//为属性A赋值
    }else if(name=="b"){//为属性B赋值
       SetA(value);
    }else{
       ...
    }
}

从上面代码中,可以知道,当要为一个实体类赋值和解析的属性比较少的时候,我们要写的代码还是可以让人接受的,但是一旦实体类的代码一多,那么整个过程就非常地恶心。通过反射,我们可以获取一个实体类中的信息,通过获取运行时的函数信息,我们又可以动态地调用函数,为实体类动态赋值。以上代码如果用反射的相关方法来写的话,就会变得异常简洁。

//这只是一段伪代码
while(str.Length!=0){//在一个大的while里面遍历整个字符串
//这里省去解析的函数
//用判断读到的名称,然后通过反射调用相应的属性进行初始化。
    MethodInfo mMethodInfo = ClassA.GetMethod(name);
    mMethodInfo.Invoke(obj1, null);
    …
}

说了这么久,给反射下个定义

反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等,。System.reflection命名空间包含的几个类,允许你反射(解析)这些元数据表的代码和反射相关的命名空间(我们就是通过这几个命名空间访问反射信息): – 引用自《C# 反射技术应用

    System.Reflection.MemberInfo
    System.Reflection.EventInfo
    System.Reflection.FieldInfo
    System.Reflection.MethodBase
    System.Reflection.ConstructorInfo
    System.Reflection.MethodInfo
    System.Reflection.PropertyInfo
    System.Type
    System.Reflection.Assembly

来一段代码示例

我们有一个HelloWorld类,我们想要通过反射动态地获取他的信息,并动态地调用他的方法。

public class HelloWorld
    {
        string myName = null;
        public HelloWorld(string name)
        {
            myName = name;
        }
        public HelloWorld()
            : this(null)
        {
        }
        public string Name
        {
            get
            { return myName; }
        }
        public void SayHello()
        {
            if (myName == null)
                System.Console.WriteLine("\t\tHello World");
            else
                System.Console.WriteLine("\t\tHello," + myName);
        }
    }

下面我们将应用反射进行获取方法名、动态创建类的实例、动态调用方法

static void Main(string[] args)
        {
            System.Console.WriteLine("列出程序集中的所有类型");
            Assembly mAssembly = Assembly.LoadFrom("ReflectionExample.exe");

            Console.WriteLine("程序集的名称是: {0}\n\n", mAssembly.GetName());
            Type[] mType = mAssembly.GetTypes();
            Console.WriteLine("以下是程序集里面的类型");
            for (int i = 0; i < mType.Length; i++)
            {
                Console.WriteLine("\t{0}.{1}", i, mType[i].Name);
            }
            Type Ht = typeof(HelloWorld);
            MethodInfo[] mMethodInfo = Ht.GetMethods();//利用反射获取HelloWorld里所有的方法
            Console.WriteLine("Hello World类中所有的方法:");
            for (int i = 0; i < mMethodInfo.Length; i++)
            {   //输出类里面所有的方法名
                Console.WriteLine("\t{0}.{1}", i, mMethodInfo[i].Name);
            }
            Console.WriteLine("利用Activator.CreateInstance创建实例");
            object obj1 = Activator.CreateInstance(Ht);//利用Activator.CreateInstance创建不同的实例obj1和obj2
            string name = "ChenZheRong";
            object obj2 = Activator.CreateInstance(Ht, name);
            MethodInfo mSayHello = Ht.GetMethod("SayHello");
            Console.WriteLine("\tobj1的输出");
            mSayHello.Invoke(obj1, null);

            Console.WriteLine("\tobj2的输出");
            mSayHello.Invoke(obj2, null);

        }

结果截图如下所示

要彻底地了解反射,我们还需要了解.NET可执行应用程序的结构。

.NET可执行应用程序结构

程序代码在编译后生成可执行的应用,我们首先要了解这种可执行应用程序的结构。

应用程序结构分为应用程序域—程序集—模块—类型—成员几个层次,公共语言运行库加载器管理应用程序域,这种管理包括将每个程序集加载到相应的应用程序域以及控制每个程序集中类型层次结构的内存布局。

程序集包含模块,而模块包含类型,类型又包含成员,反射则提供了封装程序集、模块和类型的对象。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或从现有对象中获取类型,然后调用类型的方法或访问其字段和属性。反射通常具有以下用途。

(1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。 
(2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 
(3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构造函数。 
(4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。 
(5)使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。 
(6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。 
(7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。 
(8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。 
System.Reflection.Emit命名空间的类提供了一种特殊形式的反射,可以在运行时构造类型。

 

参考连接

C# 参考:反射 -- 学习笔记整理,概念与应用

什么是反射?

C# 反射技术应用

System.Reflection 命名空间

作者:kissazi2 
出处:http://www.cnblogs.com/kissazi2/ 
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载:http://www.cnblogs.com/kissazi2/p/3293163.html

时间: 2024-09-08 19:25:41

反射原理是什么的相关文章

假笨说-从一起GC血案谈到反射原理

概述 公司之前有个大内存系统(70G以上)一直使用CMS GC,不过因为该系统对时间很敏感,偶尔会因为gclocker导致remark特别长(虽然加了-XX:+CMSScavReengeBeforeRemark参数,但是gclocker会导致remark前的YGC被delay),无法忍受这么长的暂停就只好迁移到了G1,经过一系列的调优之后算比较稳定了,这套参数便推到了全部机器上 可是就在上周突然有机器出现了Full GC,本来G1设计出来就是希望Full GC不在出现,出现Full GC一般是不

java反射原理制作对象打印工具_java

主要运用java反射原理,格式化输出java对象属性值,特别是list 和map.  MyTestUtil.java package utils; import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Iterator; impor

Java中利用反射原理拷贝对象

测试类 import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Date; public class Test {/*** 拷贝对象方法*/public static Object copy(Object obj

java.util.concurrent包源码阅读(二) java.util.concurrent.atomic包

Aomic数据类型有四种类型:AomicBoolean, AomicInteger, AomicLong, 和AomicReferrence(针对Object的)以及它们的数组类型, 还有一个特殊的AomicStampedReferrence,它不是AomicReferrence的子类,而是利用AomicReferrence实现的一个储存引用和Integer组的扩展类 首先,所有原子操作都是依赖于sun.misc.Unsafe这个类,这个类底层是由C++实现的,利用指针来实现数据操作 关于CAS

Java多线程:“JUC原子类”05之AtomicLongFieldUpdater原子

AtomicLongFieldUpdater介绍和函数列表 AtomicLongFieldUpdater可以对指定"类的 'volatile long'类型的成员"进行原子更新. 它是基于反射原理实现的. AtomicLongFieldUpdater函数列表 // 受保护的无操作构造方法,供子类使用. protected AtomicLongFieldUpdater() // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值. long addAndGet(T obj, l

Android中ActionBar以及menu的代码设置样式

  这篇文章主要介绍了Android中ActionBar以及menu的代码设置样式的相关资料,需要的朋友可以参考下 menu部分xml代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://sche

PS立体球的绘制

  20分钟绘制设计立体光感的龙珠!将从龙珠的材质设定.球体的折射与反射原理入手探究如何绘制龙珠.设计思路及方法,值得借鉴,记得交作业 分类: PS入门教程

2014年最值得掌握的趋势”幽灵按钮”

  2009年重启的的新<星际迷航>中,企业号中控系统的UI就使用了近似幽灵按钮的设计元素 那么先温故一下,什么是幽灵按钮 幽灵按钮,也就是Ghost Buttons,是一个透明的按钮,通常是矩形或者圆角矩形,仅保留基本的形制,使用细线来标识边界;按钮内的文字通常使用纤细的非衬线体字体的纯文本,来指明按钮功能. 幽灵按钮有时候也被称为"空按钮",通常会被设计得比普通的按钮更大一些.而它们之所以被命名为"幽灵",是应为这种按钮如同鬼魂一样透明,但是独特的造

如何把ResultSet转换成Java对象

    有时候我们不想使用任何框架,但又需要用JDBC实现类似于iBATIS的orm映射功能,把一个ResultSet转换成我们的JavaBeans,我们可以模仿iBATIS的方式自己写一个ResultSetMapper实现类,利用反射原理把ResultSet转换成一个JavaBeans,下面是网上的一个开源实现,主要用到的是注解和反射机制,我们先看一下使用效果: package com.heaven.mapper; import java.sql.Connection; import java