1.静态创建创建对象一般是创建类库,其中包含各种类,类中有各种方法,在所需的程序及调用时一般采用 类库名.类名 命名= new类库名.类名(); 命名.方法名(); 的方式调用 例如:
Weapon.Staff stf = new Weapon.Staff();//静态创建对象
stf.Hit();
但在已完成的程序中添加新项时对代码改动需要比较大 所以有了动态创建对象
2.动态创建对象:
过程概述:通过assembly类获取到文件的集合,添加到Type表单中(即元数据),如果获取的是所有的对象则用GetTypes();如果是根据类型的名字(字符串之类的),获取这种类型的Type对象,则用GetType(name);可以根据获取的对象类型类动态从本地或者远程动态创建对象类型。。 则用 Activator.CreateInstance(获取的类型名);创建实例,创建的实例是object类型的所以前面要加object ;通过获取的类型名可以获取该类型下的所有成员 则用 MemberInfo[] meminfo=类型名.GetMembers(); GetMembers()用来获取所有成员 GetMember(单个成员);GetMethods();获取所有的方法 GetMethods(方法名); MethodInfo hitMothod = 类型名.GetMethod(方法名);根据方法名字(字符串),获取该类型的方法成员实例 hitMothod.Invoke(obj, null);//调用obj这个对象的hitmothod所指向的方法
本次通过小例子来解释说明(vs2013) 创建一个空白解决方案,创建一个窗体程序ReflectDemo 和类库 Weapon weapon中有两个类Staff Sword 都有相同的方法
public void Hit()
{
System.Windows.Forms.MessageBox.Show("staff:员工 不同的类中显示的字不同");
}
将类库生成,在windowsfrom程序下添加对该程序类的引用,同时添加命名空间 using System.Reflection;
下面是windowsfrom中的代码及解释 窗体中共有三个button1 2 3,和两个listbox 1 2
在button1
private void button1_Click(object sender, EventArgs e)
{
//反射
//从D盘上把名字叫Weapon.dll的程序集,加载到内存里
Assembly asm = Assembly.LoadFile(@"D:\Weapon.dll");//D\\Weapon
Type[] types = asm.GetTypes();//相当于程序清单 表单 获取所有
foreach (Type item in types)//循环遍历到listbox1中
{
this.listBox1.Items.Add(item.ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
string wpName = this.listBox1.Text;
Assembly asm = Assembly.LoadFile(@"D:\Weapon.dll");
Type wptype = asm.GetType(wpName);//根据类型名字(字符串),获取这种类型的Type对象(模板)
Object obj = Activator.CreateInstance(wptype);
//动态创建对象 Activator:从本地或远程创建对象类型,或获取对现有远程对象的引用(不可继承)
MemberInfo[] memList = wptype.GetMembers();//GetMembers返回Systeam.Type的所有公共成员即(字段 属性 方法 索引 委托 事件)
//menberINfo获取有关成员属性的信息并提供对成员元数据的访问 GetMembers所有成员 GetMember单个成员 GetMethods所有方法 GetMethod单个方法
foreach (MemberInfo item in memList)
{
this.listBox2.Items.Add(item.Name);//item 的获取项很多
}
}
在button3事件下
private void button3_Click(object sender, EventArgs e)
{
//接下来就是实例化对象 调用方法实现相关需要
string wpName = this.listBox1.Text;
Assembly asm = Assembly.LoadFile("D:\\Weapon.dll");
Type wpType = asm.GetType(wpName);//根据类型名字(字符串),获取这种类型的Type对象(模板)
Object obj = Activator.CreateInstance(wpType);//动态创建对象
string methodName = this.listBox2.Text;//拿到你想调用的那个方法的名字
MethodInfo hitMothod = wpType.GetMethod(methodName);//根据方法名字(字符串),获取该类型的方法成员实例
hitMothod.Invoke(obj, null);//调用obj这个对象的hitmothod所指向的方法
}
按照如上代码便能实现最原始的动态创建实例对象,其中的关于代码的解释已标注。
3.改进,每一个事件中都需要对dll进行访问,在此将统一化 高内聚低耦合
方法:首先在app.config
<appSettings>
<add key="AssemblyPath" value="D:\Weapon.dll"/> //物理路径地址
</appSettings>
同时在from的程序下添加如下代码,同时添加引用System.Configuration
private Assembly asm = null;
public Form1()
{
InitializeComponent();
string asmPath = System.Configuration.ConfigurationManager.AppSettings["AssemblyPath"];
asm = Assembly.LoadFile(asmPath);
}
然后把每一个button事件下的
Assembly asm = Assembly.LoadFile(@"D:\Weapon.dll");
删除即可
4.再次改进,有一些实例化对象是固定的,不需要这么复杂的动态创建 所以可以用接口来实现
如果是反射的得到实例对象,那么他的默认引用类型是object的
如果想把这个object类型的对象强制转换成接口类型(反射出来的对象必须实现了这个接口)
那么这个接口不能与被反射的类,写在同一个项目里
必须把这个接口写在一个独立的项目里。
在原来的类库那重新创建一个类库,命名为ICommon即接口总类 其中定义一个接口类IHitable写入一个
public interface IHitable
{
void Hit();
}
同时生成之后在类库中添加对该接口类库的引用 同时在该类库中所有类前加一个继承关系,继承自何种接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ICommon;
namespace Weapon
{
public class Staff : IHitable
{
public void Hit()
{
System.Windows.Forms.MessageBox.Show("staff:员工 嗯当法杖");//这个是要添加引用 System.Windows.Forms.
}
}
}
同时在主窗体程序中修改button3中的代码 ;同时需要在主程序中添加对该接口dll的引用和using命名空间的引用
private void button3_Click(object sender, EventArgs e)
{
//接下来就是实例化对象 调用方法实现相关需要
string wpName = this.listBox1.Text;
// Assembly asm = Assembly.LoadFile("D:\\Weapon.dll");
Type wpType = asm.GetType(wpName);//根据类型名字(字符串),获取这种类型的Type对象(模板)
Object obj = Activator.CreateInstance(wpType);//动态创建对象
//string methodName = this.listBox2.Text;//拿到你想调用的那个方法的名字
//MethodInfo hitMothod = wpType.GetMethod(methodName);//根据方法名字(字符串),获取该类型的方法成员实例
//hitMothod.Invoke(obj, null);//调用obj这个对象的hitmothod所指向的方法
ICommon.IHitable wp = obj as ICommon.IHitable;
wp.Hit();
}