14反射程序集

1、什么是程序集?

程序集是.net中的概念。

.net中的dll与exe文件都是程序集。程序集(Assembly),可以看作是一堆相关类打一个包,相当于Java中的jar包(*)

程序集包含:类型元数据(描述在代码中定义的每一类型和成员,二进制形式)、程序元数据(程序集清单、版本号、名称等)、IL代码(这些都被装在exe或dll中)、资源文件。每个程序集都有自己的名称、版本等信息。这些信息可以通过AssemblyInfo.cs文件来定义。

使用程序集的好处:

程序中只引用必须的程序集,减小程序的尺寸。

程序集可以封装一些代码,只提供必要的访问接口。

如何添加程序集的引用?

添加路径、项目引用、GAC(全局程序集缓存)

不能循环添加引用

在C#中添加其它语言编写的dll文件的引用》(参考P/Invoke,在.net中调用非程序集的dll) extern

2、反射

反射无处不在,我们天天在使用。VS的智能提示,就是通过反射获取到类的属性、方法等。还有反编译工具也是通过反射实现。

反射就是动态获取程序集的元数据(提供程序集的类型信息)的功能。

反射就是动态获取程序集中的元数据来操作类型的

Type类实现反射的一个重要的类,通过它我们可以获取类中的所有信息,包括方法、属性等。可以动态调用累的属性、方法。Type是对类的描述。

反射就是直接通过 .dll 来创建对象,调用成员。

通过类型元数据来获取对象的一些相关信息,并且还可以实例化对象调用方法等,这个就叫做 ”反射” 。

反射让创建对象的方式发生了改变。

编译器的智能提示就是反射的一个应用。

3、Type类

Type类的使用

通过类获得Type:    Type t = typeof( person )

通过对象获得类的Type:    Type t = p.GetType( )

动态加载程序集

string path = @"F:\MyCSharp\练习\练习\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
//加载程序集
Assembly asm = Assembly.LoadFile(path);

调用 Assembly 的 GetExportedTypers 方法可以得到 Assembly 中定义的所有 public 类型

Type[] types = asm.GetExportedTypes();//获得程序集中定义的所有 public 类型  返回值是一个类型数组

调用 Assembly 的 GetTpye( name ) 方法可以得到 Assembly 中定义的全名为 name 的类型信息

//获取指定的某个类型,必须写该类型的"全名"(完全限定名称:ClassLibrary1.Person)
Type typePerson = asm.GetType("ClassLibrary1.Person");
4、动态创建对象

GetConstructor ( 参数列表 ) ;  //这是一个找到带参数的构造函数

Activator.CreateInstance( Type t )  会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果类没有无参构造函数机会报错

string path = @"F:\MyCSharp\练习\练习\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
//加载程序集
Assembly asm = Assembly.LoadFile(path);
//获得某个类型的Type
Type typeStudent = asm.GetType("ClassLibrary1.Student");
Type typePerson = asm.GetType("ClassLibrary1.Person");
Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
//使用CreateInstance(Type t) 创建对象
object student = Activator.CreateInstance(typeStudent);//调用的是无参的构造函数
object person = Activator.CreateInstance(typePerson);//调用的是无参的构造函数

Type类的方法:在编写调用插件的程序时,需要做一系列验证。

bool IsAssignableFrom( Type c );     判断当前的类型的变量是不是可以接受 c 类型变量的赋值。

 1 //1、IsAssignableFrom(),就是验证是否可以将某个类型的对象赋值给另外一个类型的变量
 2 string path = @"F:\MyCSharp\练习\练习\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
 3 //加载程序集
 4 Assembly asm = Assembly.LoadFile(path);
 5 //获得某个类型的Type
 6 Type typeStudent = asm.GetType("ClassLibrary1.Student");
 7 Type typePerson = asm.GetType("ClassLibrary1.Person");
 8 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
 9 //返回true 表示可以将 typeStudnet 的对象赋值给 typePerson 类型
10 Console.WriteLine(typePerson.IsAssignableFrom(typeStudent));
11 //是否可以把 typeStudent 对象赋值给 typeIFlyable 类型变量
12 Console.WriteLine(typeIFlyable.IsAssignableFrom(typePerson));
13 //是否可以把 typeStudent 对象赋值给 typeIFlyable 类型变量
14 Console.WriteLine(typeIFlyable.IsAssignableFrom(typeStudent));
15 Console.ReadKey();

bool IsInstanceOfType( object o );    判断对象o是否是当前类的实例(当前类可以是o的类、父类、接口)

 1 string path = @"F:\MyCSharp\练习\练习\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
 2 //加载程序集
 3 Assembly asm = Assembly.LoadFile(path);
 4 //获得某个类型的Type
 5 Type typeStudent = asm.GetType("ClassLibrary1.Student");
 6 Type typePerson = asm.GetType("ClassLibrary1.Person");
 7 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
 8 object student = Activator.CreateInstance(typeStudent);
 9 object person = Activator.CreateInstance(typePerson);
10 //person 这个对象是否是当前指定的 typePerson 的对象
11 Console.WriteLine(typePerson.IsInstanceOfType(person));//true
12 //student 这个对象是否是当前指定的 typePerson 的对象
13 Console.WriteLine(typePerson.IsInstanceOfType(student));//true
14 //person 这个对象是否是当前指定的 typeStudent 的对象
15 Console.WriteLine(typeStudent.IsInstanceOfType(person));//false
16 //student 这个对象是否是当前指定的 typeStudent 的对象
17 Console.WriteLine(typeStudent.IsInstanceOfType(student));//true
18 //person 这个对象是否是当前指定的 typeIFlyable 的对象
19 Console.WriteLine(typeIFlyable.IsInstanceOfType(person));//false
20 //student 这个对象是否是当前指定的 typeIFlyable 的对象
21 Console.WriteLine(typeIFlyable.IsInstanceOfType(student));//true
22 Console.ReadKey();

bool IsSubclassOf( Type c );    判断当前类是否是类c的子类。(与接口无关)

 1 //3、IsSubclassOf(Type c)    判断当前类是否是类 c 的子类,只是类,没有接口的事
 2 string path = @"F:\MyCSharp\练习\练习\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
 3 //加载程序集
 4 Assembly asm = Assembly.LoadFile(path);
 5 //获得某个类型的Type
 6 Type typeStudent = asm.GetType("ClassLibrary1.Student");
 7 Type typePerson = asm.GetType("ClassLibrary1.Person");
 8 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
 9 //创建指定类型的对象
10 object student = Activator.CreateInstance(typeStudent);
11 object person = Activator.CreateInstance(typePerson);
12 //判断 typeStudent 是否是 typePerson 的子类
13 Console.WriteLine(typeStudent.IsSubclassOf(typePerson));//true
14 //判断 typePerson 是否是 typeIFlyable 的子类
15 Console.WriteLine(typePerson.IsSubclassOf(typeIFlyable));//false
16 //判断 typeStudent 是否是 typeIFlyable 的子类
17 Console.WriteLine(typeStudent.IsSubclassOf(typeIFlyable));//false
18 Console.ReadKey();

IsAbstract    判断是否为抽象的,包含接口

 1 //4、IsAbstract  判断是否为抽象的,含接口
 2 string path = @"F:\MyCSharp\练习\练习\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
 3
 4 //加载程序集
 5 Assembly asm = Assembly.LoadFile(path);
 6
 7 //获得某个类型的Type
 8 Type typeStudent = asm.GetType("ClassLibrary1.Student");
 9 Type typePerson = asm.GetType("ClassLibrary1.Person");
10 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
11 Type typeMyclass1 = asm.GetType("ClassLibrary1.MyClass1");
12 Type typeMyclass2 = asm.GetType("ClassLibrary1.MyClass2");
13
14 //创建指定类型的对象
15 object student = Activator.CreateInstance(typeStudent);
16 object person = Activator.CreateInstance(typePerson);
17
18 //判断是否为抽象的,含接口
19 Console.WriteLine(typeStudent.IsAbstract);//false
20 Console.WriteLine(typePerson.IsAbstract);//false
21 Console.WriteLine(typeIFlyable.IsAbstract);//true
22 Console.WriteLine(typeMyclass1.IsAbstract);//true
23 Console.WriteLine(typeMyclass2.IsAbstract);//true
24
25 Console.ReadKey();
5、动态调用成员

MemberInfo类    抽象类,有很多子类,下面所有类都继承自 MemberInfo 类:

PropertyInfo    获取属性

1 //所有的属性
2 PropertyInfo[] properties = typePerson.GetProperties();
3 //通过循环输出每一个属性的名称
4 for (int i = 0; i < properties.Length; i++)
5 {
6     //循环输出
7     Console.WriteLine(properties[i].Name);
8 }
9 Console.ReadKey(); 

主要成员:

CanRead、CanWrite、PropertyType属性类型;

SetValue、GetValue:读取值、设置值第一个参数是实例对象,因为set、get要针对具体实例,最后一个参数 null 。pInfo.SetValue( p1, 30, null );

MethodInfo    获取方法

1 //获取 Person 类中的所有的方法
2 MethodInfo[] methods = typePerson.GetMethods();
3 //遍历获取到的所有方法的数组
4 for (int i = 0; i < methods.Length; i++)
5 {
6     //输出所有方法的方法名
7     Console.WriteLine(methods[i].Name);
8 }
9 Console.ReadKey(); 

获得某一个指定的方法

  1. 1 //获得Person类名字为SayHi的方法,并且是没有任何参数的方法
    2 MethodInfo method = typePerson.GetMethod("SayHi")


调用这个方法

  1.  1 MethodInfo method = typePerson.GetMethod("SayHi");
     2 //判断获得的方法是否为空
     3 if (method != null)
     4 {
     5     //因为SayHi()方法是一个实例方法,不是静态方法,所以调用SayHi()方法的时候,必须在某个对象上调用,所以method.Invoke() 需要传递一个具体的Person对象进去
     6     object obj = Activator.CreateInstance(typePerson);//创建一个Person对象
     7         //调用Invoke() 方法要把person创建的对象传进来
     8     method.Invoke(obj, null);//调用SayHi()方法,如果这个方法没有参数第二个参数为null
     9 }
    10 else
    11 {
    12     Console.WriteLine("找不懂啊你要调用的方法");
    13 }
    14 Console.ReadKey(); 

调用这个方法的重载方法

  1. //获得方法名为 SayHi 的重载方法(第二个参数为对应类型的参数:typeof(参数相应类型))
    MethodInfo method = typePerson.GetMethod("SayHi", new Type[] { typeof(string), typeof(string) });
    if (method != null)
    {
        //因为SayHi()方法是一个实例方法,不是静态方法,所以调用SayHi()方法的时候,必须在某个对象上调用,所以method.Invoke() 需要传递一个具体的Person对象进去
        object obj = Activator.CreateInstance(typePerson);//创建一个Person对象
        method.Invoke(obj, new object[] { "张三", "吃了吗" });//调用SayHi(string s1,string s2)重载方法
    }
    else
    {
        Console.WriteLine("找不到你要调用的方法");
    }
    Console.ReadKey();


FieldInfo    获取字段

  1. 1 //获得所有的字段
    2 FieldInfo[] fields = typePerson.GetFields();
    3 //遍历每个字段
    4 for (int i = 0; i < fields.Length; i++)
    5 {
    6         //输出每个字段名
    7     Console.WriteLine(fields[i].Name);
    8 }
    9 Console.ReadKey(); 


EventInfo    获取事件

来自为知笔记(Wiz)

时间: 2024-08-27 00:45:58

14反射程序集的相关文章

反射程序集

通过Type,我们可以对任何类型进行反射读取,同样,也可以把读取的对象的范围扩大. 一,关于程序集 在.net中,程序集是进行部署,版本控制的基本单元: System.reflection命名空间下的Assembly类型,代表了一个程序集,并包含了关于程序集的信息. 获取assembly对象的方法: loadForm 参数:程序集的文件名称(如果加载一个不属于当前项目的程序集,则要写上全名) Load  参数:提供程序集名称即可,而非文件名称. 二,反射程序集示例 首先,我们建立如下结构解决方案

反射 | 程序集

什么是程序集: 程序集是.net中的概念,net中dll和exe都是程序集,他们的区别就是exe可以直接执行(因为它有入口main函数,而dll没有,)而dll 不可以直接执行,它没有入口main函数,它是供其他程序来调用的 控制台应用程序最后编译成了exe文件,而类库编译生成了dll文件 什么是放射: 放射就是通过编程的方式,动态加载程序集,并获取里面类型,并创建对象,调用其成员的过程,这就是反射 <1> 我们来首先在解决方案下创建一个类库,命名为"TestDll"  代

2015-08-12~14 反射

反射: 若程序运行时接收到外部传入的一个对象,该对象的编译类型是Object,但程序又需要调用该对象运行类型的方法: 1.若编译和运行类型都知道,使用 instanceof判断后,强转. 2.编译时根本无法预知该对象的类属于哪些类,程序只能依靠运行时信息来发现对象和类的真实信息,这是反射就必须使用了. 3.要是想通过对象来找其对应的类名,就得使用反射. Class类和Class类实例 Class类代表Java类,它的各个实例对象分别对应各个类在内存中的字节码. 类被类加载器加载到内存中,占用一片

【C#反射程序集】

一.在.NET中,程序集是进行部署,版本控制的基本单元.System.Reflection命名空间中的Assembly类型,代表了一个程序集.并包含了关于程序集的信息. 二.获取程序集的信息: 创建一个控制台项目,添加一个类库项目,命名为Model,里面有一个User类. static void Main(string[] args) { //1.使用LoadFrom,前提当前项目有该程序集的引用 Assembly asm = Assembly.LoadFrom("Model.dll"

Type.GetType()在跨程序集反射时返回null的解决方法

在开发中,经常会遇到这种情况,在程序集A.dll中需要反射程序集B.dll中的类型.如果使用稍有不慎,就会产生运行时错误.例如使用Type.GetType("BNameSpace.ClassName")在程序集A.dll获取程序集B.dll中的类型,就会返回Null. 关于跨程序集的反射,有两点需要注意: 1.如果使用typeof,编译能通过,则跨程序集的反射一定可以正常运行.可以说,typeof是支持强类型的.比如 1 Type supType = typeof(BNameSpace

Type.GetType()与 typeof跨程序集反射

原博地址:http://www.cnblogs.com/hyl8218/archive/2010/02/19/1667440.html 上一篇的热更新还不够完善,所以另外查了下相关资料,准备做一个完整的热更新系统. 在开发中,经常会遇到这种情况,在程序集A.dll中需要反射程序集B.dll中的类型.如果使用稍有不慎,就会产生运行时错误.例如使用Type.GetType("BNameSpace.ClassName")在程序集A.dll获取程序集B.dll中的类型,就会返回Null. 关于

JavaSE_ 反射 目录(27)

黑马程序员_JavaSE学习总结第27天_反射 & 设计模式 & JDK5.7.8新特性27.01 反射_类的加载概述和加载时机27.02 反射_类加载器的概述和分类27.03 反射_反射概述27.04 反射_获取class文件对象的三种方式27.05 反射_通过反射获取无参构造方法并使用27.06 反射_通过反射获取带参构造方法并使用27.07 反射_通过反射获取私有构造方法并使用27.08 反射_通过反射获取成员变量并使用27.09 反射_通过反射获取无参无返回值成员方法并使用27.1

概述反射和序列化

1.概述反射和序列化 反射:程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象.您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性 序列化:序列化是将对象转换为容易传输的格式的过程.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.在另一端,反序列化将从该流重新构造对象. 2.什么是SOAP,有哪些应用? 答:SOAP(Simple

通过反射获取数据库的数据 将其转化为相应类型的数据

反射可以动态获取数据的类型,Type 类可以获取其中的 字段.方法.属性等. 尤其是将字段与属性做区分可以让我们可以获取,自己想获得的.废话不多说上代码. 先将数据导入的类,写下: 1 using System; 2 using UnityEngine; 3 4 namespace ARPGSimpleDemo.Skill 5 { 6 /// <summary> 7 /// 技能数据 8 /// </summary> 9 [Serializable] 10 public class