zoukankan      html  css  js  c++  java
  • 反射ORM



    七章    反射



    1节
    获取dll文件中的type-----------------------------------------------------------------------------------------------------------------------(*)

    //程序集
    程序集是.net中的概念,.dll和.exe都属于程序集
    AssemblyInfo.cs是当前程序集的一些信息(版本号)
    程序集包含:类型元数据(描述在代码中定义的每一类型和成员,二进制形式)、程序集元数据(程序集清单、版本号、名称等)、IL代码(这些都被装在exe或dll中)、资源文件。
    每个程序集都有自己的名称版本等信息。这些信息通过AssemblyInfo.cs文件来自己定义。
    //程序集得好处:
    程序中只引用必须的程序集,减小程序的尺寸。
    程序集可以封装一些代码,只提供必要的访问接口。

    //反射
    反编译工具和智能提示都是通过反射来实现的。
    反射:动态获取程序集中的元数据来操作类型的
    Type类是实现反射的一个重要的类,通过它我们可以获取类中的所有的信息,包括方法、属性等。可以动态调用属性和方法。Type是对类的描述

    //如何获取一个类中的所有属性
    //在本类中
                //1
                //Type tp = typeof(Person); //获得当前程序集指定公共类----------------------------(*)
                //2
                Person per = new Person();
                Type tp = per.GetType();//也可以获得当前实例的公共类---------------------------(*)
                MethodInfo[] methes = tp.GetMethods(); //获得当前公共类的所有公共方法
                for (int i = 0; i < methes.Length;i++ )
                {
                    Console.WriteLine(methes[i].Name);
                }
                PropertyInfo[] ps = tp.GetProperties();//获得当前公共类的所有公共属性
                foreach(PropertyInfo p in ps)
                {
                    Console.WriteLine(p.Name);
                }
    MyClass类库 (不需要引用,直接获得程序集)
    //在外部类中
                string path = @"G:RuPeng_YZK_150107Console_NETStronger_Chapter_7MyClassesinDebugMyClasses.dll";
                Assembly ass = Assembly.LoadFile(path);//加载指定路径上的程序集信息文件------------(*)
                Type[] tps = ass.GetExportedTypes();//获得此程序集信息中定义的类型--------------(*)
                foreach(Type tp in tps)
                {
                    //Console.WriteLine(tp.Name);
                    MethodInfo[] methes = tp.GetMethods(); //获得该公共类中的所有方法
                    foreach (MethodInfo meth in methes)
                    {
                        Console.WriteLine(meth.Name);
                    }
                }



    2节
    三个比较重要的方法------------------------------------------------------------------------------------------------------(*)

    //第二中获得程序集的所有公共类型,指定公共类型
                string path = @"G:RuPeng_YZK_150107Console_NETStronger_Chapter_7MyThreeClassesinDebugMyThreeClasses.dll";
                Assembly ass = Assembly.LoadFile(path);//从指定程序集路径获得程序集
                Type tpPerson = ass.GetType("MyThreeClasses.Person");//获得指定的程序集类型名称的类型实例
                Type tpStudent = ass.GetType("MyThreeClasses.Student");
                //Console.WriteLine(tp.Name);
                bool flag = tpPerson.IsAssignableFrom(tpStudent);//当前类型的实例是否可以用指定类型的实例进行赋值--true
                bool flag1 = tpStudent.IsAssignableFrom(tpPerson);//false--因为Student是Person的子类
                
                bool flag2 = tpPerson.IsSubclassOf(tpStudent);//当前类是否是指定类派生的,即是否是指定类的子类
                bool flag3 = tpStudent.IsSubclassOf(tpPerson);

                object obj = Activator.CreateInstance(tpStudent);//创建指定类型的一个实例
                bool flag4 = tpPerson.IsInstanceOfType(obj);//指定对象是否是当前类的实例

                Type tpAnimal = ass.GetType("MyThreeClasses.Animal");
                bool flag5 = tpAnimal.IsAbstract;//属性,指定类是否是抽象类
                Console.WriteLine(flag5);



    3节
    动态调用程序集中的方法------------------------------------------------------------------------------------------------(*)

    //动态调用(dynamic call)
    //需要先获得类型的方法,然后再调用这个方法
                //Person per = new Person();
                //Type tp = per.GetType();
                Type tp = typeof(Person);
                MethodInfo meth = tp.GetMethod("SayHello",new Type[]{typeof(string)});//获得这个类型中指定名称的公共方法
                object obj = Activator.CreateInstance(tp);   //创建一个指定类型的实例
                meth.Invoke(obj,new object[]{"....很想"});   //使用指定参数调用当前实例的方法    //没有参数就是null
                Console.ReadKey();
        class Person
        {
            public void SayHello(string str)
            {
                Console.WriteLine("hello,想我了吗?"+str);
            }
        }


    4节
    反射插件(Reflecting the plug-in)----------------------------------------------------------------------------------------(*)

    //做一个小写转大写的插件
    主程序--->搜索dll文件
    获得所有程序集
    获取Type
    是否实现了插件的规范(用接口方式命名这个接口)

    菜单(文件 编辑 视图 帮助)
    TextBox(Dock)
    //寻找当前程序集路径,在其所在目录的文件下,搜索指定程序集dll

    //主程序
        //窗口加载时,添加插件Editplus
            private void Form1_Load(object sender, EventArgs e)
            {
                //获得插件的路劲
                string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Lib");
                //搜索目录中与指定模式匹配的文件集dll文件
                string[] files = Directory.GetFiles(path, "*.dll");
                foreach(string file in files)
                {
                    //加载指定路径中程序集的内容
                    Assembly ass = Assembly.LoadFile(file);
                    //获得该程序集中所有的类型
                    Type[] tps = ass.GetTypes();
                    //获得接口的类型
                    Type ieditplus = typeof(IEditplus);
                    //插件程序集的所有类型中实现接口的类型
                    foreach(Type tp in tps)
                    {
                        //如果接口类型的实例可以由某一类型的实例赋予,且这一类型又不是抽象类,就可以创建这一类型的实例,去实例化获得这个接口
                        if(ieditplus.IsAssignableFrom(tp) && !tp.IsAbstract )
                        {
                            IEditplus iedit = (IEditplus)Activator.CreateInstance(tp);
                            //这个接口的插件名称就可以附加到菜单的下拉项中
                            ToolStripItem tsi = tsmView.DropDownItems.Add(iedit.Name);
                            //菜单下拉项tsi的点击事件,执行接口中的"小写转大写方法",所以需要传接口,可以用控件的tag存接口
                            tsi.Tag = iedit;//可以用当前点击控件的tag存接口
                            tsi.Click += new EventHandler(tsi_Click);
                        }
                    }
                }
            }

            private void tsi_Click(object sender, EventArgs e)
            {
                //需要获得当前控件
                ToolStripItem tsi = sender as ToolStripItem;
                //需要获得这个接口
                IEditplus iedit = tsi.Tag as IEditplus;
                //需要执行接口中的方法
                txt.Text = iedit.LittleToLarge(txt);
            }

    //插件的接口类---(主程序和子程序都需要添加对接口的引用)
    namespace ClassLibary_Notice
    {
        public interface IEditplus
        {
            string Name { get; }    //这个插件 接口的名称,是只读、不能修改的
            string LittleToLarge(TextBox tb);   //插件 接口中的小写转大写方法---文本框需要添加System.Windows.Forms的引用
        }
    }

    //插件(接口类的子类,子程序)---(需要把插件放入主程序的Lib中,使主程序可以找到实现了接口的类型)
    namespace ClassLibrary_Notice_Substring.cs
    {
        public class Editplus:IEditplus
        {
            public string Name
            {
                get { return "小写转大写"; }
            }
            public string LittleToLarge(System.Windows.Forms.TextBox tb)
            {
                return tb.Text.ToUpper();
            }
        }
    }







  • 相关阅读:
    模板 无源汇上下界可行流 loj115
    ICPC2018JiaozuoE Resistors in Parallel 高精度 数论
    hdu 2255 奔小康赚大钱 最佳匹配 KM算法
    ICPC2018Beijing 现场赛D Frog and Portal 构造
    codeforce 1175E Minimal Segment Cover ST表 倍增思想
    ICPC2018Jiaozuo 现场赛H Can You Solve the Harder Problem? 后缀数组 树上差分 ST表 口胡题解
    luogu P1966 火柴排队 树状数组 逆序对 离散化
    luogu P1970 花匠 贪心
    luogu P1967 货车运输 最大生成树 倍增LCA
    luogu P1315 观光公交 贪心
  • 原文地址:https://www.cnblogs.com/adolphyang/p/4739022.html
Copyright © 2011-2022 走看看