反射

在使用反射之前要先了解程序集
我们写好的程序最终都会被编译成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("请输入秒数");
                }
            }
        }
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/hejinyang/p/2813397.html