• .NET知识梳理——2.反射


    1. 反射

    1.1        DLL-IL-Metadata-反射

    DLL:程序集,包含IL 和Metadada

    IL:面向对象中间语言(不太好阅读)

    Metadata描述了dll、exe中的各种类、属性、方法、参数等信息。

    反射 Reflection: .NET Framework提供的帮助类库,可以读取Metadata。

    C# 高级语言经过编译器编译生成DLL/EXE,DLL/EXE中包含了Metadata和IL,CLR先读取DLL/EXE中的Metadata,然后JIT进行二次编译,编译成机器码。

    1.2        反射加载DLL,读取类、方法、特性

    1.2.1  加载DLL

       Assembly assembly = Assembly.Load("XF.DB.SqlServer");//动态加载,需要提供完整的DLL名,不需要后缀,从exe所在的路径进行查找

       Assembly assembly2 = Assembly.LoadFile(@"C:HXF_CODE2.Code5.NET CodeXF.High.NET.StudyXF.DB.SqlServerinDebugXF.DB.Sqlserver.dll");

       Assembly assembly3 = Assembly.LoadFrom("XF.DB.SqlServer.dll");

    Assembly assembly4 = Assembly.LoadFrom(@"C:HXF_CODE2.Code5.NET CodeXF.High.NET.StudyXF.DB.SqlServerinDebugXF.DB.Sqlserver.dll");

    1.2.2  读取类并创建对象

      Type type = assembly.GetType("XF.DB.SqlServer.SqlServerHelper");//获取类型,需要提供完整的类型名称

                    object sqlServerHelper = Activator.CreateInstance(type);

                    IDBHelper dbHelper = sqlServerHelper as IDBHelper;

                    dbHelper.Query();

      2.2.创建多构造函数对象:

    object ctor1 = Activator.CreateInstance(type);

                    object ctor2 = Activator.CreateInstance(type, new object[] { 123 });

                    object ctor3 = Activator.CreateInstance(type, new object[] { "Olive" });

    1.3        反射创建对象,反射+简单工厂+配置文件 

    程序可配置,通过配置文件自动切换

    实现类必须是事先已有的,且存在运行目录下

    没有写死类型,通过配置文件执行,反射创建

    可扩展:不修改原有代码,只是增加新的实现,修改配置即可支持新功能

    反射动态加载、创建对象,与配置文件结合。

    private static string typeStr = ConfigurationManager.AppSettings["IDBHelperConfig"];

    //反射动态加载、创建对象结合配置文件

                {

                    string[] typeArr = typeStr.Split(',');

                    Assembly assembly1 = Assembly.Load(typeArr[1]);

                    Type type = assembly1.GetType(typeArr[0]);

                    foreach (var ctor in type.GetConstructors())

                    {

                        Console.WriteLine(ctor.Name);

                        foreach (var parameter in ctor.GetParameters())

                        {

                            Console.WriteLine(parameter.ParameterType);

                        }

                    }

     

                    object ctor1 = Activator.CreateInstance(type);

                    object ctor2 = Activator.CreateInstance(type, new object[] { 123 });

                    object ctor3 = Activator.CreateInstance(type, new object[] { "Olive" });

                }

    1.4        选修:破坏单例 创建泛型

    1.4.1 反射破坏单例

    反射破坏单例(调用私有的构造函数)

    //反射破坏单例(调用私有的构造函数)

                    Assembly assembly5 = Assembly.Load("XF.DB.SqlServer");

                    Type type1 = assembly.GetType("XF.DB.SqlServer.Singleton");

                    Singleton singleton4 = (Singleton)Activator.CreateInstance(type1, true);

                    Singleton singleton5 = (Singleton)Activator.CreateInstance(type1, true);

                    Singleton singleton6 = (Singleton)Activator.CreateInstance(type1, true);

                    Console.WriteLine($"{object.ReferenceEquals(singleton4, singleton6)}");

    1.4.2 反射创建泛型

       Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");

                    Type type2 = assembly.GetType("XF.DB.SqlServer.GenericClass`3");//`3为类型占位符,有几个类型就是几,这里有3个类型

                    Type typeMake = type2.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });//确定泛型的类型

                    object genericInstance = Activator.CreateInstance(typeMake);//在创建实例的时候,一定要明确具体的类型

                    GenericClass<string,int,DateTime> gc = genericInstance as GenericClass<string, int, DateTime>;

                    gc.Show("Olive", 116, DateTime.Now);

    1.5        反射调用实例方法、静态方法、重载方法

    1.5.1  反射调用实例方法

    Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");

                    Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");

                    object test = Activator.CreateInstance(type2);

     

                    MethodInfo method = type2.GetMethod("Show");//调用无参函数

                    method.Invoke(test, null);

     

                    MethodInfo method1 = type2.GetMethod("Show1");//调用有参函数

                    method1.Invoke(test,new object[] { "Olive" });

    1.5.2  反射调用静态方法

    Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");

                    Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");

                    object test = Activator.CreateInstance(type2);

      MethodInfo method6 = type2.GetMethod("Show4");//调用静态函数,实例可要

                    method6.Invoke(test, new object[] { "Olive" });

     

                    MethodInfo method7 = type2.GetMethod("Show4");//调用静态函数,实例为空

                    method7.Invoke(null, new object[] {  "Olive" });

    1.5.3  反射调用重载方法

    Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");

                    Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");

                    object test = Activator.CreateInstance(type2);

    MethodInfo method2 = type2.GetMethod("Show2", new Type[] {  });//调用重载函数,无参

                    method2.Invoke(test, null);

     

                    MethodInfo method3 = type2.GetMethod("Show2", new Type[] {typeof(int) });//调用重载函数

                    method3.Invoke(test, new object[] { 116 });

     

                    MethodInfo method4 = type2.GetMethod("Show2", new Type[] {typeof(string),typeof(int) });//调用重载函数

                    method4.Invoke(test, new object[] { "Olive",116 });

     

                    MethodInfo method5 = type2.GetMethod("Show2", new Type[] { typeof(int) ,typeof(string)});//调用重载函数

                    method5.Invoke(test, new object[] { 116,"Olive" });

    1.6        调用私有方法 调用泛型方法

    1.6.1  反射调用私有方法

      Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");

                    Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");

                    object test = Activator.CreateInstance(type2);

    MethodInfo method8 = type2.GetMethod("Show3",BindingFlags.Instance|BindingFlags.NonPublic);//调用私有函数

                    method8.Invoke(test, new object[] { "Olive" });

    1.6.2  反射调用泛型方法

      Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");

                    Type type2 = assembly6.GetType("XF.DB.SqlServer.GenericMethod");

                    object test = Activator.CreateInstance(type2);

     

                    MethodInfo method = type2.GetMethod("Show");//调用无参函数

                    var methodNew = method.MakeGenericMethod(new Type[] { typeof(string), typeof(int), typeof(DateTime) });

     

                    methodNew.Invoke(test,new object[] { "Olive", 116, DateTime.Now });

    1.6.3  反射调用泛型类型+泛型方法

    Type type2 = assembly6.GetType("XF.DB.SqlServer.GenericDouble`1");

                    Type type3 = type2.MakeGenericType(new Type[] { typeof(int) });

     

                    object test = Activator.CreateInstance(type3);

     

                    MethodInfo method = type3.GetMethod("Show");

                    var methodNew = method.MakeGenericMethod(new Type[] { typeof(string),  typeof(DateTime) });

     

                    methodNew.Invoke(test, new object[] { 116, "Olive", DateTime.Now });

    1.7        反射字段和属性,分别获取值和设置值

    1.7.1  反射字段、获取、设置值

    Assembly assembly6 = Assembly.Load("XF.Model");

                    Type type = assembly6.GetType("XF.Model.People");

                    object people = Activator.CreateInstance(type);

                    foreach(var field in type.GetFields())

                    {

                        Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(people)}");

                        if (field.Name.Equals("Description"))

                            field.SetValue(people, "Good boy");

                    }

    1.7.2  反射属性、获取、设置值

      Assembly assembly6 = Assembly.Load("XF.Model");

                    Type type = assembly6.GetType("XF.Model.People");

                    object people = Activator.CreateInstance(type);              

     

                    foreach(var prop in type.GetProperties())

                    {

                        Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(people)}");

                        if (prop.Name.Equals("Id"))

                            prop.SetValue(people, 116);

                    }

    1.8        反射的好处和局限

    好处:动态

    局限:使用麻烦

    避开编译器检查

    性能问题:正常情况下基本上不存在性能问题

  • 相关阅读:
    【Java学习】01. Java基本介绍及环境搭建
    vue组件之间的传值
    检测上传的文件类型js实现方式
    正则表达式学习笔记
    Nuxt.js学习笔记
    Vue+typescript+vuex项目实践学习笔记
    项目依赖&开发依赖
    vuex学习笔记
    export与export default的区别
    ES6 数组去重方法
  • 原文地址:https://www.cnblogs.com/Olive116/p/12340323.html
Copyright © 2020-2023  润新知