标签:
什么是程序集:放射就是通过编程的方式,动态加载程序集,并获取里面类型,并创建对象,调用其成员的过程,这就是反射
《1》 我们来首先在解决方案下创建一个类库,命名为“TestDll” 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestDll { public class Person { public Person(string name,int age,string email) { this.Name = name; this.Age = age; this.Email = email; } public Person() { } public string Name { get; set; } public int Age { get; set; } public string Email { get; set; } public void Say() { Console.WriteLine("Hi....."); } public void SayHello() { Console.WriteLine("Hi,我是SayHello无参数重载方法!"); } public void SayHello(string msg) { Console.WriteLine(msg); } public int Add(int x, int y) { return x + y; } } public interface IFlyable { void Fly(); } public class Student : Person { } internal class Teacher : Person { } public class MyClass1:IFlyable { public void Fly() { Console.WriteLine(""); } } public delegate void MyDelegate(); public struct MyStruct { } struct MyStruct1 { } }
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace 反射 { public class MyClass { public string Name { get; set; } public void Say() { Console.WriteLine("你好......"); } private void SayHello() { Console.WriteLine("大家好才是真的好"); } } class Program { static void Main(string[] args) { //对于Type的介绍 //1.怎么获取一个类型的Type (即:该类型的类型原数据),办法有两种 //1.1当有类型的对象的时候的获取方式 MyClass mc = new MyClass(); Type t1= mc.GetType(); //这样就获得了MyClass类型的Type //1.2只有类,没有类型对象的时候 Type t2 = typeof(MyClass); //这样就获得了MyClass类型的Type //-----------------------那么拿到这个Type能干啥?-----------------------// //1可以获取当前类型的父类是谁? Console.WriteLine(t1.BaseType.ToString()); //可以获取当前的类型的父类的父类是谁? //Console.WriteLine(t1.BaseType.BaseType.ToString()); //2获取当前类型中的所有公有字段 FieldInfo[] fieldinfo= t1.GetFields(); //3获取当前类型中的所有公有属性 PropertyInfo[] propertyinfo= t1.GetProperties(); //4获取当前类型中的所有公有方法 MethodInfo[] methodinfo = t1.GetMethods(); //5获取当前类型中的所有公有事件 EventInfo[] eventinfo = t1.GetEvents(); //6获取当前类型中的所有公有构造函数 ConstructorInfo[] constructorinfo = t1.GetConstructors(); //................等等 //---------------------------------------------// //动态加载程序集 (Assembly类表示一个程序集,它是一个抽象的类,它里面有些静态成员) //根据程序的路径,动态加载一个程序集 Assembly asm=Assembly.LoadFile(@"D:\学习\Solution1\TestDll\bin\Debug\TestDll.dll"); //获取该程序集中的所有类型 Type[] types= asm.GetTypes(); foreach (var v in types) { //Console.WriteLine(v.FullName); //获取该程序集中所有类型的名称,打印产生如下输出 /* TestDll.Person TestDll.IFlyable TestDll.Student TestDll.Teacher TestDll.MyClass1 TestDll.MyDelegate TestDll.MyStruct TestDll.MyStruct1 */ } //我们一般我们只获取程序集中的所有公有类型(即:获取程序集中所有public的类型) Type[] publicTypes = asm.GetExportedTypes(); foreach (var v in publicTypes) { Console.WriteLine(v.FullName); //打印一下,产生如下输出 /* TestDll.Person TestDll.IFlyable TestDll.Student TestDll.MyClass1 TestDll.MyDelegate TestDll.MyStruct */ } //-------有时候我们只需要获取某个类型 比如我们现在想获取这个Person类型-------------// Type ptype = asm.GetType("TestDll.Person"); //注意:括号中应该带上Person类的命名空间TestDll; 即:命名空间+类名 //-------------------现在我们来调用Person类中的Say()方法---------// //想调用Person类中的Say()方法就先获取这个Say()方法 MethodInfo methodA = ptype.GetMethod("Say"); //拿到了这个Say()方法了,然后我们就调用这个Say()方法....可以怎么调用呢? //methodinfo.Invoke这个方法是用来调用Say()这个方法的,可是它里面有两个参数, //第一个参数:表示Say()这个方法所属的类的对象; 因为Say()方法是非静态方法,非静态方法只有类对象才能调用 //第二个参数:表示Say()这个方法的参数,如果没有参数就写个null就可以了。因为一个方法可以有多个参数,所以它是一个object的数组类型 //问题来了,既然我们想得到Say()这个方法所属的类的对象,我们又法直接方法Person类型,所以不能直接new一个Person类型的对象,我们又另外一种方法来创建Person类型的对象 object objA=Activator.CreateInstance(ptype); //这样就会根据这个ptype创建了Person类的一个对象 methodA.Invoke(objA, null); //在这里就是调用了这个Say方法 输出:Hi..... //---------------现在我们来调用Person类中的SayHello()的无参数重载方法------------// MethodInfo methodB = ptype.GetMethod("SayHello", new Type[] { }); //注意 第二个参数表示SayHello()这个方法的参数,因为方法可以有多个参数,所有第二个参数是一个数组,而我在数组里什么都没有放,即放了一个空数组,就表示获取Person类下面没有参数的SayHello()方法 object objB = Activator.CreateInstance(ptype); methodB.Invoke(objB,null); //--------------现在我们来调用Person类中的SayHello()有1个参数的重载方法---------// MethodInfo methodC = ptype.GetMethod("SayHello", new Type[] { typeof(string) }); //获取SayHello()这个方法中有一个string类型的参数的方法 object objC = Activator.CreateInstance(ptype); methodC.Invoke(objC, new object[] {"参数1" }); //输出:参数1 //-------------------------通过Type来创建对象----------------// //我们上面有样式过 根据Person的Type创建一个Person类型对象 object objD = Activator.CreateInstance(ptype); //但是通过以上这种方式来创建对象也是有一点问题的。因为如果这个Person没有无参构造函数,只有一些有参数的构造函数,我想通过调用一些有参数的构造函数来创建对象,这个时候使用Activator.CreateInstance(ptype);就不行了,因为这里Activator.CreateInstance(ptype);就是调用无参构造函数创建对象的,它没发指定有参构造函数来创建对象,所以我们只能通过另外一种办法来创建 //-------通过调用指定的构造函数来创建对象--------- //1.获取指定的构造函数 ConstructorInfo info = ptype.GetConstructor(new Type[] { typeof(string), typeof(int), typeof(string) }); //2.调用构造函数来创建对象 object objE =info.Invoke(new object[] { "张三", 25, "123@qq.com" }); //这个objeE就是通过指定构造函数来创建的对象 //通过放射获取指定对象的属性的值 比如这里我要获取Person类的Name属性值 //1.首先的获取这个Person类下面的Name属性 PropertyInfo pinfo = ptype.GetProperty("Name"); string name=pinfo.GetValue(objE, null).ToString(); //获取objE这个对象的Name属性值 Console.WriteLine(name); //同样我们也可以设置属性的值 pinfo.SetValue(objE, "李四"); //设置objE这个对象的Name属性值 string name2 = pinfo.GetValue(objE, null).ToString(); Console.WriteLine(name2); //输出一下重新设置的Name值 Console.ReadKey(); } } }
标签:
原文地址:http://blog.csdn.net/fanbin168/article/details/45798967