• C#反射的基本应用


    反射描述了在运行过程中检查和处理程序元素的功能。反射可以完成以下任务:

    • 枚举类型的成员;
    • 实例化新对象;
    • 执行对象的成员;
    • 查找类型的信息;
    • 查询程序集的信息;
    • 检查应用于某种类型的自定义特性;
    • 创建和编译新程序集。

    1、Type类

    Type类是一个抽象的基类。只要实例化一个Type对象,实际上就是实例化了Type的一个派生类。获取给定类型的Type引用三种方式:

    • 使用c#的typeof运算符。其参数是类型的名称(不放在引号中);
    • 使用GetType()方法,所有的类都是继承自Object类(值类型实际上也是如此),其具有该方法。
    • 调用Type类的静态方法GetType():Type t=Type.GetType("System.Double")。

    1.1、Type的属性

    Type的属性可以分为三类。首先,许多属性都可以获取包含与类相关的各种名称的字符串。

    • Name:数据类型名
    • FullName:数据类型的完全限定名(包括命名空间名)
    • Namespace:在其中定义数据类型的名称空间名

    其次,属性能获取Type对象的引用。

    • BaseType:该Type的直接基本类型
    • UnderlyingSystemType:该Type在.net运行库中映射到类型(某些.net基类实际上映射到由IL识别的特定预定义类型)

      最后,许多布尔类型属性表示这种类型是一个类,还是一个枚举等。这些属性包含:IsAbstract、IsArray、IsClass、IsEnum、IsInterface、IsPointer、IsPrimitive(一种预定义的基本数据类型)、IsPublic、IsSealed和IsValueType等。

    1.2、Type的方法

       Type的大多数方法都用于获取对应数据类型的成员信息:构造函数、属性、方法和事件等。它的许多方法都具有想同的模式。

    • GetConstrucotr(), GetConstrucotrs():获取ConstrucotrInfo对象类型;
    • GetEvent(), GetEvents():获取EventInfo对象类型;
    • GetField(), GetFields():获取FieldInfo对象类型;
    • GetMember(), GetMembers(), GetDefaultMembers():获取MemberInfo对象类型;
    • GetMethod(), GetMethods():获取MethodInfo对象类型;
    • GetProperty(), GetProperties(): 获取PropertyInfo对象类型。

      GetMember()和GetMembers()方法返回数据类型的任何成员或所有成员的详细信息,不管这些成员是构造函数、属性或方法等。

    2、Assembly类

      Assembly类允许访问给定程序集的元素据,可以加载和执行程序集的方法等。使用Assembly实例之前需要加载对应的程序集到正在运行的进程中。使用静态成员Assembly.Load()或Assembly.LoadFrom(),Load()方法的参数是程序集的名称,运行库会在哥哥位置上搜索该程序集,位置包括本地目录和全局程序集缓存。LoadFrom()方法参数是完整的程序集路径。

    3、使用示例:

      相关源码:https://files.cnblogs.com/files/pilgrim/MyReflection.rar

    3.1、加载程序集,获取对应的特性和创建对象:

     Console.WriteLine("*****************Reflection***********");
     Assembly assembly = Assembly.Load("DB.MySql");//获取当前路径下的dll,不需要后缀
     Module[] modules = assembly.GetModules();//获取程序集中的所有模块
     Type[] types = assembly.GetTypes();//获取程序中所有的类型
     Attribute[] attributes= assembly.GetCustomAttributes().ToArray();//获取程序中所有的自定义特性
    
     Type dbHlperType = assembly.GetType("DB.MySql.MySqlHlper");
     object oDBHlper = Activator.CreateInstance(dbHlperType);//创建对象(默认构造函数)
     DB.Interface.IDBHlper dBHlper = oDBHlper as DB.Interface.IDBHlper;
     dBHlper.Query();

      为使得程序更加灵活,可以将上面的代码进行修改优化。使用应用程序配置文件+工厂方法,在配置文件中添加代码:

      <add key="IDBHlper" value="DB.MySql,DB.MySql.MySqlHlper"/>。

      添加类读取相关数据:

    public class SimpleFactory
    {
        /// <summary>
        /// 程序集名称
        /// </summary>
        public static string DllName { get; private set; }
        /// <summary>
        /// 程序集中的某个类型名称
        /// </summary>
        public static string TypeName { get; private set; }
        static SimpleFactory()
        {
            //从配置文件中读取数据
            string[] iDBHlperConfig = ConfigurationManager.AppSettings["IDBHlper"].Split(',');
            DllName = iDBHlperConfig[0].Trim();
            TypeName = iDBHlperConfig[1].Trim();
        }
    
        /// <summary>
        /// 创建实例
        /// </summary>
        /// <returns></returns>
        public static DB.Interface.IDBHlper CreateInstance()
        {
            Assembly assembly = Assembly.Load(DllName);//加载程序集
            Type type = assembly.GetType(TypeName);//获取对应的类型
            object dbHlper = Activator.CreateInstance(type);//创建实例
            return dbHlper as DB.Interface.IDBHlper;
        }
    }

      在代码调用时使用:

     //使用工厂方法创建实例
     DB.Interface.IDBHlper dBHlper2 = SimpleFactory.CreateInstance();
     dBHlper2.Query();
     Console.WriteLine();

    3.2、使用程序集调用多构造函数、破坏单例、创建泛型类型等:

    Assembly assembly = Assembly.Load("DB.SqlServer");//获取当前路径下的dll,不需要后缀
    Type dbHlperType = assembly.GetType("DB.SqlServer.SqlServerHlper");
    ConstructorInfo[] constructorInfos = dbHlperType.GetConstructors();//获取所有的公共构造函数
    //一个int类型参数的构造函数
    object oDBHlper1 = Activator.CreateInstance(dbHlperType, new object[] { 520 });
    //一个字符串类型参数的构造函数
    object oDBHlper2 = Activator.CreateInstance(dbHlperType,new object[] { "一个字符串参数"});
    //一个字符串类型和一个int类型参数的构造函数
    object oDBHlper3 = Activator.CreateInstance(dbHlperType, new object[] { "一个字符串和一个int参数",520 });
    //调用私有构造函数
    object oDBHlper4 = Activator.CreateInstance(dbHlperType, true);
    Console.WriteLine();
    //获取泛型类型,其有三个泛型参数
    Type genericType = assembly.GetType("DB.SqlServer.GenericType`3");//`3是占位符,三个泛型参数
    //将三个泛型参数类型的泛型创建为: float int string类型的类
    Type type = genericType.MakeGenericType(typeof(float), typeof(int), typeof(string));
    object oGeneric = Activator.CreateInstance(type);
    Console.WriteLine(oGeneric.ToString());

    3.3、使用反射调用实例方法、静态方法、私有方法等: 

    Assembly assembly = Assembly.Load("DB.MySql");//获取当前路径下的dll,不需要后缀
    Type type = assembly.GetType("DB.MySql.MySqlHlper");
    object obj = Activator.CreateInstance(type);//创建对象(默认构造函数)
    foreach (var item in type.GetMethods())
    {
        Console.WriteLine(item.Name);
    }
    MethodInfo method = type.GetMethod("Query", new Type[] { } );//如果重载了,必须传入参数类型
    method.Invoke(obj, null);//谁调用,调用传入的参数
    //method.Invoke(null, null);//该方法只适用于静态函数
    MethodInfo method1 = type.GetMethod("Query", new Type[] { typeof(int) });
    method1.Invoke(obj, new object[] { 520});//谁调用,调用传入的参数
    MethodInfo method2 = type.GetMethod("Query",new Type[] { typeof(string)});
    method2.Invoke(obj, new object[] { "字符串" });//谁调用,调用传入的参数
    I travel alone,not to be alone.
  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/pilgrim/p/9220133.html
Copyright © 2020-2023  润新知