放射就是通过编程的方式,动态加载程序集,并获取里面类型,并创建对象,调用其成员的过程,这就是反射
《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