C# 反射Reflection——反射反射程序员的快乐
一、什么是反射
反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata。
反射是无处不在的,MVC-Asp.Net-ORM-IOC-AOP 几乎所有的框架都离不开反射
如下图是程序执行的过程,高级语言经过编译器编译得到dll/exe文件,这里的文件可以跨平台使用,编译后的文件中其实包括了metadata元数据(数据清单,描述了DLL/exe里面的各种信息)和IL(也是一种面向对象语言,但是不太好阅读)在经过CLR/JIT编译得到可以被计算机所执行的机器码。
二、反射的使用
一)反射动态加载程序集
Assembly assembly1 = Assembly.LoadFrom(@"DB.MySql.dll");//当前路径 Assembly assembly2 = Assembly.LoadFile(@"D:\ruanmou\MyReflection\bin\Debug\DB.MySql.dll");//dll、exe文件完整路径 Assembly assembly3 = Assembly.Load(@"DB.MySql");//dll、exe名称 dll/exe需要拷贝至程序bin文件夹下
二)简单工厂生产对应实体
/// <summary> /// 简单工厂生产对应实体 /// </summary> /// <returns></returns> public static T CreateInstance<T>() { Assembly assembly = Assembly.Load(ConfigurationManager.AppSettings["DalDllName"]);//加载dll Type dalType = assembly.GetType(ConfigurationManager.AppSettings["DalTypeName"]);//获取类型 return (T)Activator.CreateInstance(dalType);//创建对象 //var newType = dalType.MakeGenericType(typeof(T));//获取泛型类型 //return (T)Activator.CreateInstance(newType);创建泛型类型对象 }
三)常用方法
Type[] types= assembly.GetTypes();//获取程序集所有类型 Type type= assembly.GetType("TypeName");//获取指定类型 MethodInfo[] methods= type.GetMethods();//获取所有方法 MethodInfo method= type.GetMethod("methodName");//获取指定方法 PropertyInfo[] propertys= type.GetProperties();//获取所有属性 PropertyInfo property = type.GetProperty("propertyName");//获取指定属性 FieldInfo[] fields= type.GetFields();//获取所有字段 FieldInfo field = type.GetField("fieldName");//获取指定字段 Attribute attribute = type.GetCustomAttribute(typeof(DisplayNameAttribute));//获取指定特性
反射调用多参数构造函数,方法
/// <summary> /// 反射测试类 /// </summary> public class ReflectionTest { #region Identity /// <summary> /// 无参构造函数 /// </summary> public ReflectionTest() { Console.WriteLine("这里是{0}无参数构造函数", this.GetType()); } /// <summary> /// 带参数构造函数 /// </summary> /// <param name="name"></param> public ReflectionTest(string name) { Console.WriteLine("这里是{0} 有参数构造函数", this.GetType()); } public ReflectionTest(int id) { Console.WriteLine("这里是{0} 有参数构造函数", this.GetType()); } #endregion #region Method /// <summary> /// 无参方法 /// </summary> public void Show1() { Console.WriteLine("这里是{0}的Show1", this.GetType()); } /// <summary> /// 有参数方法 /// </summary> /// <param name="id"></param> public void Show2(int id) { Console.WriteLine("这里是{0}的Show2", this.GetType()); } /// <summary> /// 重载方法之一 /// </summary> /// <param name="id"></param> /// <param name="name"></param> public void Show3(int id, string name) { Console.WriteLine("这里是{0}的Show3", this.GetType()); } /// <summary> /// 重载方法之二 /// </summary> /// <param name="name"></param> /// <param name="id"></param> public void Show3(string name, int id) { Console.WriteLine("这里是{0}的Show3_2", this.GetType()); } /// <summary> /// 重载方法之三 /// </summary> /// <param name="id"></param> public void Show3(int id) { Console.WriteLine("这里是{0}的Show3_3", this.GetType()); } /// <summary> /// 重载方法之四 /// </summary> /// <param name="name"></param> public void Show3(string name) { Console.WriteLine("这里是{0}的Show3_4", this.GetType()); } /// <summary> /// 重载方法之五 /// </summary> public void Show3() { Console.WriteLine("这里是{0}的Show3_1", this.GetType()); } /// <summary> /// 私有方法 /// </summary> /// <param name="name"></param> private void Show4(string name) { Console.WriteLine("这里是{0}的Show4", this.GetType()); } /// <summary> /// 静态方法 /// </summary> /// <param name="name"></param> public static void Show5(string name) { Console.WriteLine("这里是{0}的Show5", typeof(ReflectionTest)); } #endregion }
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer"); Type type = assembly.GetType("Ruanmou.DB.SqlServer.ReflectionTest"); object oTest = Activator.CreateInstance(type);//反射调用无参数构造函数 object oTest2 = Activator.CreateInstance(type, new object[] { 123 });//反射调用一个int类型参数构造函数 foreach (var method in type.GetMethods()) { Console.WriteLine(method.Name); foreach (var parameter in method.GetParameters())//获取方法参数 { Console.WriteLine($"{parameter.Name} {parameter.ParameterType}"); } } { ReflectionTest reflection = new ReflectionTest(); reflection.Show1(); } { MethodInfo method = type.GetMethod("Show1"); //if() method.Invoke(oTest, null);//oTest调用无参数方法 } { MethodInfo method = type.GetMethod("Show2"); method.Invoke(oTest, new object[] { 123 });//oTest调用一个int类型参数方法 } { MethodInfo method = type.GetMethod("Show3", new Type[] { }); method.Invoke(oTest, null);//oTest调用无参数重载方法 } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) }); method.Invoke(oTest, new object[] { 123 });//oTest调用一个int类型参数重载方法 } { MethodInfo method = type.GetMethod("Show5"); method.Invoke(oTest, new object[] { "String" });//静态方法实例可以要 } { MethodInfo method = type.GetMethod("Show5"); method.Invoke(null, new object[] { "string" });//静态方法实例也可以不要 }
var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(oTest, new object[] { "私有方法" });
反射调用泛型方法、泛型类
public class GenericClass<T, W, X> { public void Show(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } } public class GenericMethod { public void Show<T, W, X>(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } } public class GenericDouble<T> { public void Show<W, X>(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } }
{ Console.WriteLine("********************GenericMethod********************"); Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer"); Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericMethod"); object oGeneric = Activator.CreateInstance(type); //foreach (var item in type.GetMethods()) //{ // Console.WriteLine(item.Name); //} MethodInfo method = type.GetMethod("Show"); var methodNew = method.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) }); object oReturn = methodNew.Invoke(oGeneric, new object[] { 123, "test", DateTime.Now }); } { Console.WriteLine("********************GenericMethod+GenericClass********************"); Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer"); Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericDouble`1").MakeGenericType(typeof(int)); object oObject = Activator.CreateInstance(type); MethodInfo method = type.GetMethod("Show").MakeGenericMethod(typeof(string), typeof(DateTime)); method.Invoke(oObject, new object[] { 345, "teat", DateTime.Now }); }
反射破坏单例
/// <summary> /// 单例模式:类,能保证在整个进程中只有一个实例 /// </summary> public sealed class Singleton { private static Singleton _Singleton = null; private Singleton() { Console.WriteLine("Singleton被构造"); } static Singleton() { _Singleton = new Singleton(); } public static Singleton GetInstance() { return _Singleton; } }
{ Console.WriteLine("********************Singleton********************"); Singleton singleton1 = Singleton.GetInstance(); //new Singleton(); Singleton singleton2 = Singleton.GetInstance(); Singleton singleton3 = Singleton.GetInstance(); Singleton singleton4 = Singleton.GetInstance(); Singleton singleton5 = Singleton.GetInstance(); Console.WriteLine($"{object.ReferenceEquals(singleton1, singleton5)}"); //反射破坏单例---就是发射调用私有构造函数 Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer"); Type type = assembly.GetType("Ruanmou.DB.SqlServer.Singleton"); Singleton singletonA = (Singleton)Activator.CreateInstance(type, true); Singleton singletonB = (Singleton)Activator.CreateInstance(type, true); Singleton singletonC = (Singleton)Activator.CreateInstance(type, true); Singleton singletonD = (Singleton)Activator.CreateInstance(type, true); Console.WriteLine($"{object.ReferenceEquals(singletonA, singletonD)}"); }
本文参考文档:
https://www.cnblogs.com/loverwangshan/p/9883243.html;
微软文档地址:
.NET Framework 中的反射:https://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/reflection;
System.Reflection Namespace:https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection?view=netframework-4.7.2;
Type Class:https://docs.microsoft.com/zh-cn/dotnet/api/system.type?view=netframework-4.7.2;
作者:德乌姆列特
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。
博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!