• 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.
  • 相关阅读:
    ASP.NET常用的三十三种代码
    asp.net获取IP地址
    Inside Microsoft Sql Server 2005 TSQL Programming 学习笔记
    动态SQL与SQL注入(一)动态SQL
    (二)SQL 注入
    WCF 安全
    C# 运算符重载和 implicit关键字
    分页那回事
    thinking
    Moss css
  • 原文地址:https://www.cnblogs.com/pilgrim/p/9220133.html
Copyright © 2020-2023  润新知