C#编程(七十九)---------- 反射

反射

在介绍翻着之前,先说两个小案例

B超:什么叫B超呢?就是透过肚皮能看到你内脏的情况,不用打开肚子才能看.这是什么样的一种技术呢?B超是B型超声波,它可以透过肚皮通过向你体内发射B型超声波,当超声波遇到内脏壁的时候就会产生一定的“回音”反射,然后把“回音”进行处理就可以显示出内脏的情况了

地球内部结构:地球的内部结构大体可以分为三层:地壳、地幔和地核。地壳是固体,地核是液体,地幔则是半液半固的结构(中学地理的内容,大家还记得吧?)。如何在地球表面不用深入地球内部就知道其内部的构造呢?对,向地球发射“地震波”,“地震波”分两种一种是“横波”,另一种是“纵波”。“横波”只能穿透固体,而“纵波”既可穿透固体又可以穿透液体。通过在地面对纵波和横波的反回情况,我们就可以大体断定地球内部的构造了

其实说这两个例子并没有什么卵用,就是想告诉你,他们都有一个共同点,就是从一个对象的外部去了解对象内部的构造,而且都是李永乐波的反射功能.在.NET中的反射也可以实现从对象的外部来了解对象(或程序集)内部结构的功能,就算比不知道这个对象(或程序集)是个什么东西,就像科学家不用刨开地球,就能知道地球的构造一样,另外.NET中的反射还可以动态的创建出对象并执行他其中的方法.

反射是.NET中重要的机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类,结构,委托,接口和枚举等)的成员的信息.有了反射,即可对每一个类型了如指掌.另外还可以直接创建对象,及时这个对象的类型在编译时还不知道.

反射的用途:

(1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找烈性并创建该类型的实例.

(2)使用Moudule了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有的全区方法或其他特定的给全局方法.

(3)使用ConstructorInfo了解方法的名称,返回类型,参数,访问修饰符和实现详细信息等

(4)使用MethodInfo了解方法的名称,返回类型,参数,访问修饰符和实现详细信息(如abstract或virtual)

(5)使用FiedInfo了解字段的名称,访问修饰符和实现详细信息等,并获取或设置字段值

(6)使用EventInfo了解事件的名称,事件处理程序数据类型,自定义属性,生命类型和反射类型等,添加或移除事件处理程序.

(7)使用PropertyInfo了解属性的名称,数据类型,声明类型,反射类型和只读或可写状态等,获取或设置属性值

(8)使用ParameterInfo了解参数的名称,数据类型,是输入参数还是输出参数,一次参数在方签名中的位置等.

(需要记住吗?不需要,用的时候知道有这么一回事,能查到就行)

反射用到的命名空间:(主要有三个)

System.Reflection

System.Type

System.Reflection.Assembly

反射用到的主要类

System.Type类----通过这个类可以访问任何给定数据类型的信息

System.Feflection.Assembly----他可以用于访问给定程序集的信息,或者把这个程序集加载到程序中.

System.Type类:

System.Type类对于反射起着核心的作用.但他是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法,字段,属性来查找有关该类型的所有信息.

获取给定类型的type饮用有三种常用方式:

a.使用C#typeof运算符

Type t=typeof(string);

b.使用对象GetType()方法

string s=”hahaha”;

Type t=s.GetType();

c.还可以调用Type类的静态方法GetType().

Type t=Type.GetType(“”);

上面这三类代码都是获取string类型的Type,再取出string类型的Type引用t后,我们就可以通过t来探测string类型的结构了.

string n = "grayworm";

Type t = n.GetType();

foreach (MemberInfo mi in t.GetMembers())

{

Console.WriteLine("{0}\t{1}", mi.MemberType, mi.Name);

}

Type类的属性


属性名


说明


Name


数据类型名


FullName


数据类型的完全限定名


Namespace


定义数据类型的命名空间名


IsAbstract


指示该类型是否是抽象类型


IsArray


指示该类型是否是数组


IsClass


指示该类型是否是类


IsEnum


指示该类型是否是枚举


IsInterface


指示该类型是否是接口


IsPublic


指示该类型是否是公有的


IsSealed


指示该类型是否是密封类


IsValueType


指示该类型是否是值类型

Type类的方法:

GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息
        GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息
        GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
        GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息
        GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息
        GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息
        GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息
    可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo, PropertyInfo和其他类的Invoke()方法。

查看类中的构造函数

class Program

{

static void Main(string[] args)

{

NewClassw nc = new NewClassw();

Type t = nc.GetType();

ConstructorInfo[] ci = t.GetConstructors();    //获取类的所有构造函数

foreach (ConstructorInfo c in ci) //遍历每一个构造函数

{

ParameterInfo[] ps = c.GetParameters();    //取出每个构造函数的所有参数

foreach (ParameterInfo pi in ps)   //遍历并打印所该构造函数的所有参数

{

Console.Write(pi.ParameterType.ToString() + " " + pi.Name + ",");

}

Console.WriteLine();

}

Console.ReadKey();

}

}

public class NewClassw

{

public NewClassw(int age, string name)

{ }

public NewClassw()

{ }

}

用构造函数动态生成对象:

Type t = typeof(NewClassw);
        Type[] pt = new Type[2];
        pt[0] = typeof(string);
        pt[1] = typeof(string);
        //根据参数类型获取构造函数 
        ConstructorInfo ci = t.GetConstructor(pt); 
        //构造Object数组,作为构造函数的输入参数 
        object[] obj = new object[2]{"grayworm","hi.baidu.com/grayworm"};   
        //调用构造函数生成对象 
        object o = ci.Invoke(obj);    
        //调用生成的对象的方法测试是否对象生成成功 
        //((NewClassw)o).show();

用Activator生成对象:

class Program

{

static void Main(string[] args)

{

Type t = typeof(NewClassw);

//构造函数的参数

object[] obj = new object[2] { "hello","world"};

//用Activator的CreateInstance静态方法,生成新对象,构造函数的参数类型需要一致

object o = Activator.CreateInstance(t,"hello","world");

((NewClassw)o).show();

Console.ReadKey();

}

}

public class NewClassw

{

public NewClassw(string name  , string sex)

{ }

public NewClassw()

{ }

public void show()

{

Console.WriteLine("hello,syx");

}

}

产看类中的属性:

class Program

{

static void Main(string[] args)

{

NewClassw nc = new NewClassw();

Type t = nc.GetType();

PropertyInfo[] pis = t.GetProperties();

foreach (PropertyInfo item in pis)

{

Console.WriteLine(item.Name);

}

Console.ReadKey();

}

}

public class NewClassw

{

public string Name { get; set; }

public string Sex { get; set; }

}

查看类中的public方法:

class Program

{

static void Main(string[] args)

{

NewClassw nc = new NewClassw();

Type t = nc.GetType();

//这里有两个GetMethod方法,一个返回一个数组,一个返回一个MethodInfo类型

MethodInfo[] mis = t.GetMethods();

foreach (MethodInfo item in mis)

{

Console.WriteLine(item.ReturnType+" "+item.Name);

}

//连继承自object的方法都有了

Console.ReadKey();

}

}

public class NewClassw

{

public void show() { }

public void Function() { }

private void Method() { }

}

查看类中public字段:

NewClassw nc = new NewClassw();
        Type t = nc.GetType();
        FieldInfo[] fis = t.GetFields();
        foreach (FieldInfo fi in fis)
        {
            Console.WriteLine(fi.Name);
        }

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

class Program

{

static void Main(string[] args)

{

NewClassw nc = new NewClassw();

Type t = nc.GetType();

object obj = Activator.CreateInstance(t);

//取得ID字段 , 字段必须是public的,下同

FieldInfo fi = t.GetField("ID");

//给ID字段赋值

fi.SetValue(obj, "k001");

//取得MyName属性

PropertyInfo pi1 = t.GetProperty("MyName");

//给MyName属性赋值

pi1.SetValue(obj, "grayworm",null);

PropertyInfo pi2 = t.GetProperty("MyInfo");

pi2.SetValue(obj, "hi.baidu.com/grayworm", null);

//取得show方法

MethodInfo mi = t.GetMethod("show");

//调用show方法

mi.Invoke(obj, null);

Console.ReadKey();

}

}

public class NewClassw

{

//类的字段

public string ID;

//类的属性

public string MyName { get; set; }

public string MyInfo { set; get; }

//类的方法

public void show()

{

Console.WriteLine("我是show方法,我很牛逼");

}

}

System.Reflection.Assembly类

Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例.使用Assembly类可以降低程序集之间的耦合,有利于软盒结构的合理化.

通过程序集名称返回Assembly对象

Assembly ass = Assembly.Load("reflecting");

通过DLL文件名称返回Assembly对象

Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");

通过Assembly获取程序集中类

Type t = ass.GetType("reflecting.NewClassw");   //参数必须是类的全名

通过Assembly获取程序集中所有的类

Type[] t = ass.GetTypes();

//通过程序集的名称反射

class Program

{

static void Main(string[] args)

{

Assembly ass = Assembly.Load("reflecting");

Type t = ass.GetType("reflecting.NewClassw");

object o = Activator.CreateInstance(t, "grayworm", "http://hi.baidu.com/grayworm");

MethodInfo mi = t.GetMethod("show");

mi.Invoke(o, null);

Console.ReadKey();

}

}

public class NewClassw

{

public NewClassw(string name, string sex)

{ }

public NewClassw()

{ }

public void show()

{

Console.WriteLine("hello,syx");

}

}

//通过DLL文件全名反射其中的所有类型
    Assembly assembly = Assembly.LoadFrom("xxx.dll的路径");
    Type[] aa = a.GetTypes();

foreach(Type t in aa)
    {
        if(t.FullName == "a.b.c")
        {
            object o = Activator.CreateInstance(t);
        }
    }

时间: 2024-12-24 23:07:41

C#编程(七十九)---------- 反射的相关文章

第三百七十九节,Django+Xadmin打造上线标准的在线教育平台—xadmin的安装

第三百七十九节,Django+Xadmin打造上线标准的在线教育平台-xadmin的安装 xadmin介绍 xadmin是基于Django的admin开发的更完善的后台管理系统

(七十九)c#Winform自定义控件-导航菜单

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492  来都来了,点个[推荐]再走吧,谢谢 NuGet Install-Package HZH_C

ActionScript3游戏中的图像编程(连载七十九)

总目录:http://blog.csdn.net/iloveas2014/article/details/38304477 4.3.6 ColorMatrix中的矩阵数学 ColorMatrix是DynamicMatrix的子类,它一初始化就固定了矩阵的尺寸:5*5(为什么不是5*4呢,相信这个问题我不需要再次解释了),并且填入单位矩阵的数据: 该类有5个方法,前4个分别对应AdjustColor的亮度,对比度,饱和度和色相属性,最后一个是getFlatArray,它的唯一作用就是把矩阵中的有效

C#高级编程七十天----dynamic类型

dynamic类型 C#新增了dynamic关键字,正是因为这一个小小的关键字,C#像前迈进了一大步. dynamic是一个类型关键,声明为dynamic的类型与"静态类型"(这里的静态是指编译时确定的类型,例如int,double类型)相比最大的特定它是"动态类型",它会在运行时尝试调用方法,这些方法的存在与否不是编译时期检查的,而是在运行时查找,如果方法存在并且参数正确,会正确调用,否则会抛出异常. 案例: dynamic d = Console.Out; dy

一起talk C栗子吧(第一百七十九回:C语言实例--字符和字符串输出函数二)

各位看官们,大家好,上一回中咱们说的是字符和字符串输出函数的例子,这一回咱们继续说该例子.闲 话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在上一回中介绍了字符和字符串输出函数的用法,満篇都是理论,古语云:纸上得来终觉浅,绝知此事要躬行.这一回中我们要把这些纸上得来理论应用于实践中,让我们一起动手去实践吧. 接下来,我们将通过具体的代码来说明如何使用字符输出函数,以及使用时的注意事项: int main() { char ch = 'a'; char *str = "hello

第一百七十九节,jQuery-UI,知问前端--按钮 UI

jQuery-UI,知问前端--按钮 UI 学习要点: 1.使用 button 按钮 2.修改 button 样式 3.button()方法的属性 4.button('action', param) 5.单选.复选按钮 按钮(button),可以给生硬的原生按钮或者文本提供更多丰富多彩的外观.它不单单 可以设置按钮或文本,还可以设置单选按钮和多选按钮. 一.使用 button 按钮 使用 button 按钮 UI 的时候,不一定必须是 input 按钮形式,普通的文本也可以设置成 button

053(七十九)

391. 391.When setting up the Flashback Data Archive, which of these key parameters are required? (Choose all that apply.) A. Tablespace name B. Storage quota C. Retention D. Table name E. Create a default archive 392. 392.To clean up old records that

第二百七十九节,MySQL数据库-pymysql模块

MySQL数据库-pymysql模块 pymysql模块是python操作数据库的一个模块 connect()创建数据库链接,参数是连接数据库需要的连接参数使用方式: 模块名称.connect() 参数: host=数据库ip port=数据库端口 user=数据库用户名 passwd=数据库密码 db=数据库名称 cursor()创建数据库操作游标,无参使用方式: 游标变量.cursor() execute()操作数据库,参数1 sql语句,参数2 字符串占位符变量使用方式: 游标变量.exe

C#高级编程七十五天----C#使用指针

在C#中使用指针的语法 假设想在C#中使用指针,首先对项目进行过配置: 看到属性了吗?单击: 看到那个同意不安全代码了吗?选中 然后将有关指针,地址的操作放在unsafe语句块中.使用unsafekeyword是告诉编译器这里的代码是不安全的. unsafekeyword的使用: (1)放在函数前,修饰函数,说明在函数内部或函数的形參涉及到指针操作: unsafe static void FastCopy(byte[] src, byte[] dst, int count) { // Unsaf