• 反射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();
            }
        }
    }







  • 相关阅读:
    js打印的两种方法
    C# VS2010中,用微软自带的System.Data.OracleClient来连接Oracle数据库
    js获取本月第几周和本年第几周
    [转]优化数据库大幅度提高Oracle的性能
    sass的循环for,while,each
    sass的mixin,extend,placeholder,function
    float,absolute脱离文档流的总结
    React ref的用法
    cloneNode与事件拷贝
    mobx动态添加observable
  • 原文地址:https://www.cnblogs.com/adolphyang/p/4739022.html
Copyright © 2020-2023  润新知