C# 反射

反射是一种动态分析程序集、模块、类型、字段等目标对象的机制,它的实现依托于元数据。元数据是存储在PE 文件中的数据块,它详细记录了程序集或模块内部的结构、引用的类型和程序集和清单

一、加载dll,读取相关信息

            //加载程序集
            Assembly assembly = Assembly.Load("kzttest");

            //获取程序集中所有的类
            Type[] type = assembly.GetTypes();

            //获取程序集中特定类
            Type tItem = assembly.GetType("kzttest.Generics");

            //获取特定类中的所有构造函数
            ConstructorInfo[] cInfor = tItem.GetConstructors();
            //函数实现
            cInfor[0].Invoke(null);

            //获取特定类中的所有属性
            PropertyInfo[] cOutfor = tItem.GetProperties();
            for (int i = 0; i < cOutfor.Length; i++)
            {
                Console.WriteLine($"name:{cOutfor[i].Name},type:{cOutfor[i].PropertyType.FullName}");
            }

            //获取特定类中的所有方法
            MethodInfo[] methordInfo = tItem.GetMethods();

            //获取特定类中的所有接口
            Type[] typeInter = tItem.GetInterfaces();

二、反射创建对象

1、通过Activator.CreateInstance()方法来创建对象
2、反射创建对象的代码
//1.加载程序集
Assembly assembly = Assembly.Load("DB.SQLServer");
//2.获取程序集中的特定类
Type tItem = assembly.GetType("DB.SQLServer.ReflectionTest");
 //3.1 无参构造函数
Activator.CreateInstance(tItem);
 //3.2 一个参数的构造函数
Activator.CreateInstance(tItem ,"1");
//3.3 两个参数的构造函数
 Activator.CreateInstance(tItem , 1,"2");
3、反射破坏单例,调用私有构造函数
单例代码
public sealed class Singleton
    {
        private Singleton()
        {
            Console.WriteLine("初始化一次");
        }

        private static Singleton Instance = new Singleton();

        public static Singleton CreateInstance()
        {
            return Instance;
        }
    }
破坏单例,调用私有构造函数代码
            //加载程序集
            Assembly assembly = Assembly.Load("kzttest");

            //获取程序集中特定类
            Type tItem = assembly.GetType("kzttest.Singleton");

            //创建对象
            Activator.CreateInstance(tItem, true);

三、IOC(反射+简单工厂+配置文件)

通过XML动态创建对象
注:传统创建对象、接口创建对象和直接反射创建对象   都已经发布 生成dll,无法动态修改
配置文件:
<appSettings>
    <!--直接修改配置文件,可以修改数据库连接牛逼,可以直接切换 oracle 、mysql数据库,发布后可以直接通过改配置文件,切换数据库,代码什么也不用改,体会:反射+面向接口编程-->
    <!--前提:相应的DBHelper类必须满足接口约束,需要把Oracle或MySql的dll文件拷贝到Reflection中的bin文件中  -->
    <!--SQLServer改为:         -->
    <!--<add key="IDBHelper-dllName" value="DB.SQLServer"/>
    <add key="IDBHelper-className" value="DB.SQLServer.DBHelper"/>-->
    <!--Oracle改为:         -->
    <!--<add key="IDBHelper-dllName" value="DB.Oracle"/>
    <add key="IDBHelper-className" value="DB.Oracle.DBHelper"/>-->
    <!--MySql改为:         -->
    <add key="IDBHelper-dllName" value="DB.MySql"/>
    <add key="IDBHelper-className" value="DB.MySql.DBHelper"/>
  </appSettings>
简单工厂:
/// <summary>
    /// 简单工厂,创建对象
    /// </summary>
    public class SimpleFactory
    {
        private static string IDBHelperdllName = ConfigurationManager.AppSettings["IDBHelper-dllName"];
        private static string IDBHelperClassName = ConfigurationManager.AppSettings["IDBHelper-className"];

        public static IDBHelper CreateDBHelper()
        {
            Assembly assembly = Assembly.Load(IDBHelperdllName);
            Type type = assembly.GetType(IDBHelperClassName);
            object obj = Activator.CreateInstance(type);
            return (IDBHelper)obj;
        }

    }
调用:
Console.WriteLine("------------------------------------4. IOC(反射+简单工厂+配置文件)--------------------------------------");
//4. IOC(反射+简单工厂+配置文件)(不需要直接添加对其引用,只需要把相应的程序生成路径改成Reflection中即可)
IDBHelper idb3 = SimpleFactory.CreateDBHelper();
idb3.Query();

四、反射调用

            //加载程序集
            Assembly assembly = Assembly.Load("kzttest");

            //获取程序集中特定类
            Type tItem = assembly.GetType("kzttest.Generics");

            //创建对象
            object obj = Activator.CreateInstance(tItem);


            Console.WriteLine("---------------------------------2.1 调用无参、有参的实例方法-------------------------------------");
            //获取指定方法 只能一对一 不可重载  后面通过参数实现
            MethodInfo methord = tItem.GetMethod("Say2");
            //调用 无参
            methord.Invoke(obj, null);

            //获取指定方法 只能一对一 不可多态
            MethodInfo methord3 = tItem.GetMethod("Say3");
            //调用 有参
            methord3.Invoke(obj, new object[] { "有参啊" });

            Console.WriteLine("---------------------------------2.3 调用重载方法(需要在创建方法的时候,把类型传进去)-------------------------------------");
            //调用重载方法  需要在创建方法的时候,把类型传进去
            MethodInfo methord4 = tItem.GetMethod("Do", new Type[] { });
            methord4.Invoke(obj, null);

            MethodInfo methord5 = tItem.GetMethod("Do", new Type[] { typeof(string) });
            methord5.Invoke(obj, new object[] { "11" });

五、好处、局限

1、反射的好处:
  • 反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。
  • 有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。
2、局限
性能没有直接创建对象好


posted @ 2023-08-28 10:39  不争丶  阅读(58)  评论(0编辑  收藏  举报