• 反射


    在使用反射之前要先了解程序集
    我们写好的程序最终都会被编译成exe或dll。程序集(Assembly)通常表现为一个文件(.exe或.dll文件),
    除此之外程序集还包含资源文件,类型元数据(描述在代码中定义的每一类型和成员,二进制形式)、IL代码(这些都被装在exe或dll中)
    通过Assembly类可以获取程序集信息
    AppDomain.CurrentDomain.GetAssemblies()获取当前程序集加载的外部程序集
    Assembly.LoadFile(),动态从文件加载Assembly,不需要在编译的时候引用。
     
    反射无处不在,我们天天在使用。Vs的智能提示,就是通过反射获取到类的属性、方法等。还有反编译工具也是通过反射实现
     
    反射就是动态获取程序集的元数据(提供程序集的类型信息)的功能
     
    Type类实现反射的一个重要的类,通过它我们可以获取类中的所有信息包括方法、属性等。可以动态调用类的属性、方法。 Type是对类的描述
     
    Type类的使用:
     
    •通过类获得Type:Type t = typeof(Person)
     
    •通过对象获得类的Type:Type t = p.GetType()
     
    •调用Assembly的GetExportedTypes方法可以得到Assembly中定义的所有的public类型。
    View Code
    •调用Assembly的GetTypes()方法可以得到Assembly中定义的所有的类型。
     
    •调用Assembly的GetType(name)方法可以得到Assembly中定义的全名为name的类型信息。
     
    动态创建对象
    Activator.CreateInstance(Type t)会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果类没有无参构造函数就会报错。
     
    Type类方法
    bool IsAssignableFrom(Type c)判断当前的类型的变量是不是可以接受c类型变量的赋值。
    public class Student:Person{}
    
    Person p=new Student();
    
    typeof(Person ).IsAssignableFrom((typeof(Student)));//true
    
    因为Student s=new Person ();肯定不成立
    所以typeof(Person ).IsAssignableFrom((typeof(Student)))就为false
    bool IsInstanceOfType(object o):判断对象o是否是当前类的实例(当前类可以是o的类、父类、接口)
    bool IsSubclassOf(Type c):判断当前类是否是类c的子类.
     
    动态调用成员
    MemberInfo类  抽象类,有很多子类,下面讲的类都继承自它,获取程序集成员的相关信息(类型、方法、事件、字段和属性)
     
    PropertyInfo 获取属性 
    •主要成员:CanRead、CanWrite、PropertyType属性类型;SetValue、GetValue:读取值,设置值,第一个参数是实例对象,因为set、get要针对具体实例,最后一个参数null。pInfo.SetValue(p1, 30, null)
                Person p = new Person();
                Type type = p.GetType();
    
                PropertyInfo[] pis = type.GetProperties();
                foreach (PropertyInfo item in pis)
                {
                    if (item.Name == "Name")
                    {
                        item.SetValue(p, "张三", null);
                    }
                }
               
                Console.WriteLine(p.Name);
    MethodInfo 获取方法
    •MethodInfo都是和具体对象不相关的,所以需要第一个参数指定要执行的对象。
     
    FieldInfo 获取字段
     
    EventInfo 获取事件
     
    自己写插件:
    1.写一个接口,用来提供名称,跟执行方法
    IPlugin
        public interface IPlugin
        {
            string Name
            {
                get;
            }
            string Execute(string str);
        }

    2.两个实现了接口类:自动关机的,查字典的

    ShutDown
     class ShutDown:IPlugin
        {
            public string Name
            {
                get { return "定时关机"; }
            }
            string IPlugin.Execute(string 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();
                return null;
            }
        }
    Dictionary
      class Dictionary:IPlugin
        {
            public string Name
            {
                get { return "字典" ;}
            }
    
            public string Execute(string str)
            {
                Dictionary<string, string> dic = new Dictionary<string, string>();
                dic.Add("eat", "");
                dic.Add("food","食物");
                if (dic.ContainsKey(str))
                {
                    return dic[str];
                }
                else
                {
                    return "没有要查的单词";
                }
            }
        }

    3.在windows应用程序的Debug目录下新建一个Plugins文件夹,上面两个应用程序编译好后,把ShutDown.dll,Dictionary.dll放到该文件夹里,还需要添加接口的引用

    From
      private void Form1_Load(object sender, EventArgs e)
            {
                //1.获取程序集路径
                string path = AppDomain.CurrentDomain.BaseDirectory;
                path = Path.Combine(path,"Plugins");
                //2.获取dll文件详细名称
                string[] strs = Directory.GetFiles(path, "*.dll");
                foreach (string item in strs)
                {
                    //3程序集内容
                    Assembly ass = Assembly.LoadFile(item);
                    //4找要程序集中定义的所以类型
                    Type[] types = ass.GetTypes();
                    foreach (Type type in types)
                    {
                        //5该类型是实现了接口的类
                        if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsAbstract && type.IsClass)
                        {
                          //object o=  Activator.CreateInstance(type);
                          //MethodInfo mi= type.GetMethod("");
                          //mi.Invoke(o, new object[] { });
                            IPlugin ip = Activator.CreateInstance(type) as IPlugin;
                             
                            ToolStripItem tsi=  tsmi.DropDownItems.Add(ip.Name);
                            tsi.Tag = ip; 
                            tsi.Click += new EventHandler(tsi_Click);
                        }
                    }
                }
            }
    
            void tsi_Click(object sender, EventArgs e)
            {
                ToolStripItem tsi = sender as ToolStripItem;
                 if (tsi != null)
                {
                    IPlugin ip = tsi.Tag as IPlugin;
                    if (!string.IsNullOrEmpty(textBox1.Text))
                    {
                       string a = ip.Execute(textBox1.Text);
                        MessageBox.Show(a);
                    }
                    else
                    {
                        MessageBox.Show("请输入秒数");
                    }
                }
            }
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    oracle数据库迁移---windows环境下
    Tomcat内存溢出(java.lang.OutOfMemoryError: PermGen space)
    64位win系统上面tomcat6启动不了 window不能再本地计算机启动
    linux学习之一些琐碎知识点
    mysql备份与还原
    linux学习中遇到的各种故障与解决方法
    Jmeter调试工具---Debug Sampler
    python+requests接口自动化测试框架实例详解教程
    互联网架构的演变
    面试时如何考察应聘者的素质?
  • 原文地址:https://www.cnblogs.com/hejinyang/p/2813397.html
Copyright © 2020-2023  润新知