• C#基础精华08(反射,程序集)


    什么是程序集?
    程序集是.net中的概念。
    .net中的dll与exe文件都是程序集。(exe与dll的区别?)
    程序集(Assembly),可以看做是一堆相关类打一个包,相当于java中的jar包(*)。
    程序集包含:类型元数据(描述在代码中定义的每一类型和成员,二进制形式)、程序集元数据(程序集清单、版本号、名称等)、IL代码(这些都被装在exe或dll中)、资源文件。每个程序集都有自己的名称、版本等信息。这些信息可以通过AssemblyInfo.cs文件来自己定义。
    使用程序集的好处?
    程序中只引用必须的程序集,减小程序的尺寸。
    程序集可以封装一些代码,只提供必要的访问接口。
    如何添加程序集的引用?
    添加路径、项目引用、GAC(全局程序集缓存)
    不能循环添加引用

    在c#中添加其他语言编写的dll文件的引用。(参考P/Invoke,在.net中调用非程序集的dll)extern


    反射

    反射:就是动态获取程序集中的元数据来操作类型的。
    Type类实现反射的一个重要的类,通过它我们可以获取类中的所有信息包括方法、属性等。可以动态调用类的属性、方法。 Type是对类的描述。如何获取Person类中的所有属性?
    反射就是直接通过.dll来创建对象,调用成员。
    先通过一个普通类介绍Type.(Person)
    通过类型元数据来获取对象的一些相关信息,并且还可以实例化对象调用方法等,这个就叫做“反射”。
    反射让创建对象的方式发生了改变。
    编译器的智能提示就是反射的一个应用。

    反射:简单的理解就是通过类型元数据创建对象、调用对象的成员等。


    Type类

    Type类的使用
    通过类获得Type:Type t = typeof(Person)
    通过对象获得类的Type:Type t = p.GetType()
    “c:abc.dll”
    Assembly asm=Assembly.LoadFile(“c:abc.dll”);
    调用Assembly的GetExportedTypes方法可以得到Assembly中定义的所有的public类型。
    调用Assembly的GetTypes()方法可以得到Assembly中定义的所有的类型。
    调用Assembly的GetType(name)方法可以得到Assembly中定义的全名为name的类型信息。
    插件:扩展主程序功能的dll.


    Type type=typeof(Person);//没对象
                Type ty = per.GetType();//有对象
    //获取所有的字段属性
    // FieldInfo[]fileinfo= ty.GetFields();
                //获取所有的公共属性
                PropertyInfo[]propertyin= ty.GetProperties();
    //获取所有的方法
                MethodInfo[]methinfo= ty.GetMethods();
                //获取所有的事件
                EventInfo[]eventinfo= ty.GetEvents();
     //获取所有的成员
                MemberInfo[]member= type.GetMembers();
    ===================================================================================
     Assembly asm= Assembly.LoadFile(@"E:基础加强10061练习题MyClassLibraryinDebugMyClassLibrary.dll");
                Type[]types1= asm.GetExportedTypes();//获取所有公共的
                Type[] types2 = asm.GetTypes();//获得所有的
                foreach (Type item in types1)
                {
                    Console.WriteLine(item.Name);
                }
                Console.ReadKey();


    ============================================================
    foreach (MethodInfo item in methinfo)
                {
                    //没有获取私有方法
                    Console.WriteLine(item.Name);
                }
    ============================
    //Type t = typeof(Person);
                ////类的全名称
                //Console.WriteLine(t.FullName);
                ////类所在的程序集的全名称
                //Console.WriteLine(t.Assembly.FullName);


    ////获取程序集中所有公共的类型
                //Type[] types = ass.GetExportedTypes();
                //foreach (Type type in types)
                //{
                //    Console.WriteLine(type.Name);
                //}
                ////获取程序集中所有的类型
                //Type[] tys =  ass.GetTypes();
                //foreach (Type item in tys)
                //{
                //    Console.WriteLine(item.Name);
                //}
                ////根据名称获得一个类型
                //Type tPerson = ass.GetType("抽象类.Circle");
                //Console.WriteLine(tPerson.Name);
    =======================================
     Type ty= asm.GetType("MyClassLibrary.Person");


    动态创建对象

    Activator.CreateInstance(Type t)会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果类没有无参构造函数就会报错。
    GetConstructor(参数列表);//这个是找到带参数的构造函数。
    Type类的方法:在编写调用插件的程序时,需要做一系列验证。
    bool IsAssignableFrom(Type c):(直译:是否可以从c赋值)判断当前的类型的变量是不是可以接受c类型变量的赋值。
    typeof(IPlugin).IsAssignableFrom(t)
    bool IsInstanceOfType(object o):判断对象o是否是当前类的实例(当前类可以是o的类、父类、接口)
    bool IsSubclassOf(Type c):判断当前类是否是类c的子类。类的事,没有接口的事。
    IsAbstract,判断是否为抽象的,含接口


     Assembly ass=   Assembly.LoadFile(@"E:讲课视频代码集合备课资料演示C#基础加强二次测试代码1测试代码上MyProgramClassinDebugMyProgramClass.dll");
    ============================================
     //获取公用的类
              Type[]types=  ass.GetExportedTypes();
              foreach (Type item in types)
              {
                  Console.WriteLine(item.Name);
              }
    ================================
     //获取所有类型
               //Type []types= ass.GetTypes();
               //foreach (Type item in types)
               //{
               //    Console.WriteLine(item.Name);
               //}
    =================================================
     //获取指定类型的Person
               Type typePerson= ass.GetType("MyProgramClass.Person");
               Console.WriteLine(typePerson.Name);
    ============================================================================第一个方法验证
     //判断chinese类型是否可以赋值给person
               Console.WriteLine(typePerson.IsAssignableFrom(typeChinese));
     Console.WriteLine(tyPer.IsAssignableFrom(tyChinese));//括号里的对象能不能赋值给tyPer
    =============================================================
     Type typePerson = ass.GetType("MyProgramClass.Person");
               Type typeChinese = ass.GetType("MyProgramClass.Chinese");
               Object chinese= Activator.CreateInstance(typeChinese);
               Object person= Activator.CreateInstance(typePerson);
                //判断chinese这种类型是不是chinese这种类型
               Console.WriteLine(typeChinese.IsInstanceOfType(chinese));
    =======================================================================================第二个方法验证
     Type tyPer = asm.GetType("MyClassLibrary.Person");
                Type tyChinese = asm.GetType("MyClassLibrary.Chinese");
                object objPer = Activator.CreateInstance(tyPer);
                object objChinese = Activator.CreateInstance(tyChinese);
                Console.WriteLine(tyPer.IsInstanceOfType(objChinese));


    ========================================================
     Type typePerson = ass.GetType("MyProgramClass.Person");
               Type typeChinese = ass.GetType("MyProgramClass.Chinese");
                //判断是不是子类关系,接口没有子类一说,
               Console.WriteLine(typePerson.IsSubclassOf(typeChinese));
     Console.WriteLine(tyChinese.IsSubclassOf(tyPer));判断chinese是不是Person的子类
    ==============================================
     //判断是不是抽象类含接口,不能实例化的,静态的
               Console.WriteLine(typePerson.IsAbstract);
     Console.WriteLine(tyPer.IsAbstract);
                Console.WriteLine(tyIfly.IsAbstract);
    =========================================是不是抽象的
    ==============================================



    反射调用方法:

    namespace _02反射调用方法
    {
        class Program
        {
            static void Main(string[] args)
            {
                Type tp = typeof (Person);
                //方法
                MethodInfo mt = tp.GetMethod("SayHello");
                object p= Activator.CreateInstance(tp);//创建Person对象
                mt.Invoke(p,null);//调用了SayHello方法


            }
        }


        public class Person
        {
            public void SayHello()
            {
                Console.WriteLine("你好啊");
            }
        }
    }


    动态调用成员

    MemberInfo类  抽象类,有很多子类,下面讲的类都继承自它,获取程序集成员的相关信息(类型、方法、事件、字段和属性)
    PropertyInfo获取属性
    主要成员:CanRead、CanWrite、PropertyType属性类型;SetValue、GetValue:读取值,设置值,第一个参数是实例对象,因为set、get要针对具体实例,最后一个参数null。pInfo.SetValue(p1, 30, null)
    MethodInfo获取方法
    MethodInfo都是和具体对象不相关的,所以需要第一个参数指定要执行的对象。
    FieldInfo获取字段
    EventInfo获取事件



  • 相关阅读:
    Guns项目整体结构
    基于事件的NIO多线程服务器
    Reactor模式和NIO
    ConcurrentHashMap之实现细节
    C 语言的前世今生
    Netty系列之Netty高性能之道
    java synchronized详解
    生产者/消费者模式
    当spring 容器初始化完成后执行某个方法
    Linux系统管理员需要知道的16个服务器监控命令
  • 原文地址:https://www.cnblogs.com/CSharpLover/p/5193676.html
Copyright © 2020-2023  润新知