/// 1 反射调用实例方法、静态方法、重载方法 选修:调用私有方法 调用泛型方法 /// 2 反射字段和属性,分别获取值和设置值 /// 3 反射的好处和局限 class Program { /// /// 反射的优点: 动态 /// 反射的缺点: /// 1 使用麻烦 /// 2 避开编译器检查 /// 3 性能问题!!! /// 100w次循环----- 普通方法 24ms /// 反射 9206ms /// 缓存优化,把dll加载和类型获取 只执行一次 /// 100w次循环---- 普通方法 11ms /// 反射 132ms /// 反射影响更小了, /// MVC-Asp.Net-ORM-IOC-AOP都在用反射,几乎都有缓存 /// MVC&&ORM 启动很慢,完成了很多初始化,反射的那些东西 /// 后面运行就很快 static void Main(string[] args) { { //知道方法名称,可以不做类型转换,直接调用方法 //反射创建了对象实例---有方法的名称--反射调用方法 //dll名称---类型名称---方法名称---我们就能调用方法 //MVC就是靠的这一招---调用Action //http://localhost:9099/home/index 经过路由解析---会调用--HomeController--Index方法 //浏览器输入时只告诉了服务器类型名称和方法名称,肯定是反射的 //MVC在启动时会先加载--扫描全部的dll--找到全部的Controller--存起来--请求来的时候,用Controller来匹配的---dll+类型名称 //1 MVC局限性的--Action重载--反射是无法区分---只能通过HttpMethod+特性httpget/httppost //2 AOP--反射调用方法,可以在前后插入逻辑 Assembly assembly = Assembly.Load("DB.Mysql"); Type type = assembly.GetType("DB.Mysql.ReflectionTest"); object oTest = Activator.CreateInstance(type); { MethodInfo method = type.GetMethod("Show1"); method.Invoke(oTest, null); } { MethodInfo method = type.GetMethod("Show2"); method.Invoke(oTest, new object[] { 123 }); } #region 重载方法 { MethodInfo method = type.GetMethod("Show3", new Type[] { }); method.Invoke(oTest, null); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) }); method.Invoke(oTest, new object[] { 123 }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) }); method.Invoke(oTest, new object[] { "一生为你" }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) }); method.Invoke(oTest, new object[] { 234, "心欲无痕" }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) }); method.Invoke(oTest, new object[] { "PHS", 345 }); } #endregion #region 调用静态方法 { MethodInfo method = type.GetMethod("Show5"); method.Invoke(oTest, new object[] { "张中魁" });//静态方法实例可以要 } { MethodInfo method = type.GetMethod("Show5"); method.Invoke(null, new object[] { "张中魁" });//静态方法实例也可以不要 } #endregion #region 调用私有方法 { var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(oTest, new object[] { "我是老王" }); } #endregion } #region 泛型方法 { Assembly assembly = Assembly.Load("DB.Mysql"); Type type = assembly.GetType("DB.Mysql.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, "我爱祖国", DateTime.Now }); } #endregion #region 反射字段和属性,分别获取值和设置值 { Assembly assembly = Assembly.Load("DB.Mysql"); Type type = assembly.GetType("DB.Mysql.ReflectionTest"); object oTest = Activator.CreateInstance(type); foreach (var prop in type.GetProperties()) { if (prop.Name.Equals("Id")) { prop.SetValue(oTest, 123); } else if (prop.Name.Equals("Name")) { prop.SetValue(oTest, "老王"); } Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(oTest)}"); } foreach (var field in type.GetFields()) { if (field.Name.Equals("Description")) { field.SetValue(oTest, "是个好邻居"); } Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(oTest)}"); } } #endregion Console.ReadKey(); } }
#region 反射性能测试 普通方法 24ms 反射 9206ms { long commonTime = 0; long reflectionTime = 0; { Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < 1_000_000; i++) { IDBHelper iDBHelper = new MySqlHelper(); iDBHelper.Query(); } watch.Stop(); commonTime = watch.ElapsedMilliseconds; } { Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < 1_000_000; i++) { Assembly assembly = Assembly.Load("DB.Mysql");//1 动态加载 Type dbHelperType = assembly.GetType("DB.Mysql.MySqlHelper");//2 获取类型 object oDBHelper = Activator.CreateInstance(dbHelperType);//3 创建对象 IDBHelper dbHelper = (IDBHelper)oDBHelper;//4 接口强制转换 dbHelper.Query();//5 方法调用 } watch.Stop(); reflectionTime = watch.ElapsedMilliseconds; } Console.WriteLine("commonTime={0} reflectionTime={1}", commonTime, reflectionTime); } #endregion
测试结果:
#region 缓存优化,把dll加载和类型获取 只执行一次 普通方法11ms 反射132ms { long commonTime = 0; long reflectionTime = 0; { Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < 1_000_000; i++) { IDBHelper iDBHelper = new MySqlHelper(); iDBHelper.Query(); } watch.Stop(); commonTime = watch.ElapsedMilliseconds; } { Stopwatch watch = new Stopwatch(); watch.Start(); Assembly assembly = Assembly.Load("DB.Mysql");//1 动态加载 Type dbHelperType = assembly.GetType("DB.Mysql.MySqlHelper");//2 获取类型 for (int i = 0; i < 1_000_000; i++) { object oDBHelper = Activator.CreateInstance(dbHelperType);//3 创建对象 IDBHelper dbHelper = (IDBHelper)oDBHelper;//4 接口强制转换 dbHelper.Query();//5 方法调用 } watch.Stop(); reflectionTime = watch.ElapsedMilliseconds; } Console.WriteLine("commonTime={0} reflectionTime={1}", commonTime, reflectionTime); } #endregion
测试结果:
namespace DB.Interface { public interface IDBHelper { void Query(); } }
namespace DB.Mysql { public class MySqlHelper : IDBHelper { public string name { get; set; } public MySqlHelper() { } public void Query() { } } }
namespace DB.Mysql { /// <summary> /// 反射测试类 /// </summary> public class ReflectionTest { public int Id { get; set; } public string Name { get; set; } public string Description; #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 } /// <summary> /// 泛型方法 /// </summary> /// <typeparam name="T"></typeparam> 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); } } }