你的位置:首页 > ASP.net教程

[ASP.net教程]利用C#中的反射机制来实现关机插件


插件编程技术

插件是指遵循一定的接口规范、可以动态加载和运行的程序模块。利用反射的动态加载代码能力,可以很容易的实现插件,

插件编程的要点是使用接口来定义插件的功能特征。插件的宿主程序通过接口来确认、装载和执行插件的功能,实现插件功能的所有类都必须实现定义插件的接口。

 

 

 1、首先定义一个关机的接口 IShut,生成程序集,并在UI层(Winform窗体)来添加引用

 public interface IShut  {    string Name { get; }    void ShutDownCPU(int time);  }

 

2、再通过一个类ShutDownClass 来实现接口IShut,并生成程序集,
以后就通过实现接口IShut来实现更多的功能:

class ShutDownClass : IShut  {    public string Name    {      get { return "关机插件"; }    }    public void ShutDownCPU(int time)    {      ShutDown(time);    }    public void ShutDown(int second)    {     //以下来设置关机的一些属性      Process process = new Process();      process.StartInfo.FileName = "cmd.exe";      process.StartInfo.UseShellExecute = false;      process.StartInfo.RedirectStandardInput = true;      process.StartInfo.RedirectStandardOutput = true;      process.StartInfo.RedirectStandardError = true;      process.StartInfo.CreateNoWindow = true;      process.Start();      process.StandardInput.WriteLine("shutdown -s -f -t " + second);      //process.StandardInput.WriteLine("dir c:");      process.StandardInput.WriteLine("exit");      process.Close();      process.Dispose();    }  }  

 


3、UI是通过Winform来实现的,也就通过一个控件ToolStripMenuItem

UI层是通过反射来获得ShutDownClass.dll的程序集 中的类,成员,属性

通过 GetTypes()方法可以获得程序集中的所有成员

         Assembly ass = Assembly.LoadFile(item);        //获得程序集中的成员        Type[] types = ass.GetTypes();

 

通过 Activator.CreateInstance()可以获得Type类中的对象,返回的object类型
需传入Type类型
用法:

//创建对象IShut shut = Activator.CreateInstance(types[i]) as IShut;

 

Type类:
---->IsAssignableFrom()函数,判断某一个类是否可以赋值给另一个类。是否符合里氏代换的原则!
---->IsInstanceOfType()函数,判断是否是指定类的实例。
---->IsSubclassOf()函数,判断是否是某个类的子类,注意!!!没有接口的事儿!!!!
---->IsAbstract()函数,判断某一个类是否是抽象的。

用法:

 if (typeof(IShut).IsAssignableFrom(types[i]) && !types[i].IsAbstract)

UI层的代码

 private void Form1_Load(object sender, EventArgs e)    {      //功能ToolStripMenuItem.DropDown.Items.Add("关机");      //功能ToolStripMenuItem.DropDown.Items.Add("重启");      //获得plug文件夹的全路径      string path = Path.GetFullPath("plug");      //获得plug文件夹中所有的文件      string[] files = Directory.GetFiles(path, "*.dll");      //遍历files      foreach (string item in files)      {        //item:dll文件的绝对路径        Assembly ass = Assembly.LoadFile(item);        //获得程序集中的成员        Type[] types = ass.GetTypes();        //判断是否是我们需要的成员        for (int i = 0; i < types.Length; i++)        {          if (typeof(IShut).IsAssignableFrom(types[i]) && !types[i].IsAbstract)          {            //当前的数据使我们需要的数据            //创建对象            IShut shut = Activator.CreateInstance(types[i]) as IShut;            //创建菜单            ToolStripItem tsi = 功能ToolStripMenuItem.DropDown.Items.Add(shut.Name);            //存储shut            tsi.Tag = shut;            //注册单击事件            tsi.Click += tsi_Click;          }        }      }    }    void tsi_Click(object sender, EventArgs e)    {      ToolStripItem tsi = sender as ToolStripItem;      IShut s = tsi.Tag as IShut;      s.ShutDownCPU(1200);    }

 

扩展:

如果需动态调用类中的成员:(也是Type类中的方法 )
MemberInfo:抽象父类
PropertyInfo:获取属性
MethodInfo:获取方法
FieldInfo:获取字段
EventInfo:获取事件

 

用法:

//获得单个的数据成员Assembly ass = Assembly.LoadFile(Path.GetFullPath("Common.dll"));//获得程序集中Person类型信息Type t = ass.GetType("Common.Person");  //创建Person类对象o//object o = ass.CreateInstance("Common.Person");//获得类中的单个成员方法MethodInfo m = t.GetMethod("SayHello");////调用方法m.Invoke(o, null);