• 谈谈:程序集加载和反射


    最近一直都在看关于程序集加载和反射方面的资料, 所以在这里把我所学习到的东西记录下来,方便自己以后复习,也给园子里面不懂的朋友参考。

    一、程序集的加载

    JIT编译器器将IL代码编译成本地代码时, 会查看IL代码中引用了哪些类型。在运行过程中,JIT编译器利用程序集的TypeRef和AssemblyRef元数据表来确定哪一个程序集定义了所引用的类型,然后JIT编译器将对应程序集加载到AppDomain中,在内部,CLR使用System.Reflection.Assembly类的静态方法Load来尝试加载一个程序集。然而如果我们想动态加载一个程序集时,可以使用Assembly的Load方法来动态加载程序集,其中Assembly类中还提供了其他的加载程序集方法,有LoadFrom(string path), LoadFile(stringassemblyFile)等,具体方法的使用和解释可以参照MSDN中的介绍:http://msdn.microsoft.com/zh-cn/library/xbe1wdx9

    二、反射机制

    .net中反射在运行中过程中解析程序集中的元数据,获得类型中的成员(包括字段、构造器、方法、属性、事件等)信息。

    动态加载一个程序集并获得类型中的成员

    把下面的类放在一个类库工程中,并编译生成程序集(例如为ClassLibrary1.dll,假设把dll放在D盘根目录下面)

    View Code
     1  public class ReflectTestClass
     2     {
     3        public  string name;
     4        public int age;
     5        public string Name
     6        {
     7            get { return name; }
     8            set { name = value; }
     9        }
    10 
    11        public int Age
    12        {
    13            get { return age; }
    14            set { age = value; }
    15        }
    16 
    17         /// <summary>
    18         /// No Paramter Constructor
    19         /// </summary>
    20        public ReflectTestClass()
    21        { 
    22        }
    23 
    24         /// <summary>
    25         /// Constructor with Parameter
    26         /// </summary>
    27         /// <param name="name"></param>
    28         /// <param name="age"></param>
    29         public ReflectTestClass(string names,int ages)
    30         {
    31             this.name = names;
    32             this.age = ages;
    33         }
    34 
    35         public string writeString(string name)
    36         {
    37             return "Welcome " + name;
    38         }
    39 
    40         public static string WriteName(string name)
    41         {
    42             return "Welcome "+name +" Come here";
    43         }
    44 
    45         public string WirteNopara()
    46         {
    47             return "The method is no parameter ";
    48         }
    49     }

    然后建立一个控制台程序用来动态加载上面生成的程序集和输出类型中的成员,代码中有详细的介绍。

    class Program
        {
            static void Main(string[] args)
            {
                Assembly ass;
                Type[] types;
                Type typeA;
                object obj;
                try
                {
                    // 从本地中 加载程序集 然后从程序集中通过反射获得类型的信息的,并且调用方法
                    ass = Assembly.LoadFrom(@"D:\ClassLibrary1.dll");
                    types = ass.GetTypes();
                    foreach (Type type in types)
                    {
                        Console.WriteLine("Class Name is " + type.FullName);
                        Console.WriteLine("Constructor Information");
                        Console.WriteLine("-----------------------");
                        // 获取类型的结构信息
                        ConstructorInfo[] myconstructors = type.GetConstructors();
                        ShowMessage<ConstructorInfo>(myconstructors);
    
                        Console.WriteLine("Fields Information");
                        Console.WriteLine("-----------------------");
                        // 获取类型的字段信息
                        FieldInfo[] myfields = type.GetFields();
                        ShowMessage<FieldInfo>(myfields);
    
                        Console.WriteLine("All Methods Information");
                        Console.WriteLine("-----------------------");
                        // 获取方法信息
                        MethodInfo[] myMethodInfo = type.GetMethods();
                        ShowMessage<MethodInfo>(myMethodInfo);
    
                        Console.WriteLine("All Properties Information");
                        Console.WriteLine("-----------------------");
                        // 获取属性信息
                        PropertyInfo[] myproperties = type.GetProperties();
                        ShowMessage<PropertyInfo>(myproperties);
                    }
    
                    // 用命名空间+类名获取类型
                    typeA = ass.GetType("ClassLibrary1.ReflectTestClass");
                    
                    // 获得方法名称
    
                    MethodInfo method = typeA.GetMethod("writeString");
    
                    // 创建实例
                    obj = ass.CreateInstance("ClassLibrary1.ReflectTestClass");
    
                    string result = (String)method.Invoke(obj,new string[] {"Tom"});
                    Console.WriteLine("Invoke Method With Parameter");
                    Console.WriteLine("-----------------------");
                    Console.WriteLine(result);
                    Console.WriteLine("-----------------------");
                    Console.WriteLine();
                    method = typeA.GetMethod("WriteName");
                    result = (string)method.Invoke(null,new string[] {"Tom"});
                    Console.WriteLine("Invoke Static Method with Parameter");
                    Console.WriteLine("-----------------------");
                    Console.WriteLine(result);
                    Console.WriteLine("-----------------------");
                    Console.WriteLine();
                    method = typeA.GetMethod("WirteNopara");
                    Console.WriteLine("Invoke Method with NOParameter");
                    result = (string)method.Invoke(obj, null);
                    Console.WriteLine("-----------------------");
                    Console.WriteLine(result);
                    Console.WriteLine("-----------------------");
                }
    
                catch(FileNotFoundException ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                Console.ReadLine();
            }
    
            /// <summary>
            /// 显示数组信息
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="os"></param>
            public static void ShowMessage<T>(T[] array)
            { 
                foreach(T member in array)
                {
                    Console.WriteLine(member.ToString());
                }
    
                Console.WriteLine("-----------------------");
                Console.WriteLine();
            }
        }


    筛选返回的成员种类

    可以调用Type的GetMembers,GetFields,GetMethods,GetProperties或者GetEvenents方法来查询一个类型的成员。在调用上面的任何一个方法时,都可以传递System.Reflection.BindingFlags枚举类型的一个实例,使用这个枚举类型目的是对这些方法返回的成员进行筛选。对于这个枚举类型中成员的信息可以参考MSDN:http://msdn.microsoft.com/zh-cn/library/system.reflection.bindingflags(v=VS.80).aspx

    注意:在返回一个成员集合的所有方法中, 都有一个不获取任何实参的重载版本。如果不传递BindingFlags实参,所有这些方法都返回公共成员,默认设置为BindingFlags.Public|BindingFlags.Instance|BindingFlags.Static. (如果指定Public或NonPublic,那么必须同时指定Instance,否则不返回成员)。

    如果您认为这篇文章还不错或者有所收获,您可以通过右边的“打赏”功能 打赏我一杯咖啡【物质支持】,也可以点击右下角的【店长推荐】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力


  • 相关阅读:
    [转]UNI-APP开发笔记之使用uni.navigateBack修改上一个页面值
    [转]移动端人员选择的设计思考
    [转]nginx安装及其配置详细教程
    [转]Vue 使用use、prototype自定义自己的全局组件
    [转]uniapp项目运行支付宝小程序,报错:xxx.json中没有申明component: true
    支付宝(钉钉)小程序使用uView控制台报错Cannot read property 'title-all' of undefined
    [转]commonJS规范和require,import区别
    [转]module.exports和export详解
    [转]如何在组件中去使用vuex的值和方法?
    [转]CryptoJS中AES256(CBC)加密算法简单使用
  • 原文地址:https://www.cnblogs.com/zhili/p/AssemblyLoad_and_Reflection.html
Copyright © 2020-2023  润新知