7

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

 2 years ago
source link: https://www.cnblogs.com/Olive116/p/12340323.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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_CODE\02.Code\05.NET Code\XF.High.NET.Study\XF.DB.SqlServer\bin\Debug\XF.DB.Sqlserver.dll");

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

Assembly assembly4 = Assembly.LoadFrom(@"C:\HXF_CODE\02.Code\05.NET Code\XF.High.NET.Study\XF.DB.SqlServer\bin\Debug\XF.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        反射的好处和局限

好处:动态

局限:使用麻烦

避开编译器检查

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK