zoukankan      html  css  js  c++  java
  • 利用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);

     

     

  • 相关阅读:
    浏览器打开developers.weixin.qq.com开头的网站加载特别慢或者无法打开
    微信小程序在微信开发者工具中打开时为何提示“小程序重启耗时过久,请确认业务逻辑中是否有复杂运算,或者死循环”?
    解决VMware Workstation 15 与Device/Credential Guard不兼容的问题
    Gitee同步项目后内容一致MD5不同
    Python2.7安装easy_install和pip
    php连接数据库
    css画三角形
    css的9个常用选择器
    Javafx弹窗
    javafx将数据库内容输出到tableview表格
  • 原文地址:https://www.cnblogs.com/Raymond201508/p/4769610.html
Copyright © 2011-2022 走看看