static void Main(string[] args) { try { #region 创建连接 { Console.WriteLine("==========创建连接============="); //IDBHelper iDBHelper = new MySqlHelper(); IDBHelper iDBHelper = new SqlServerHelper(); //当MySqlHelper换成SqlServerHelper 就必学修改现有的代码,重新编译然后发布,为了提高效率我们可以利用反射来解决这一问题。 } #endregion #region 加载DLL { Console.WriteLine("==========加载DLL=========="); //根据名称加载程序集 //Assembly assembly = Assembly.Load("Gs.DB.MySql"); //根据完整路径加载程序集 //Assembly assembly1 = Assembly.LoadFile(@"C:\Users\wango\source\repos\Reflection\Gs.DB.MySql\bin\Debug\Gs.DB.MySql.dll"); //根据名称加载程序集 Assembly assembly2 = Assembly.LoadFrom("Gs.DB.SqlServer.dll"); //根据完整路径加载程序集 //Assembly assembly3 = Assembly.LoadFrom(@"C:\Users\wango\source\repos\Reflection\Gs.DB.MySql\bin\Debug\Gs.DB.MySql.dll"); ///** ///以上四个assembly获取的结果都是一样的 ///看起来LoadFile和LoadFrom作用是一样,他们两个有什么区别呢? ///LoadFile加载dll文件时只会加载指定的dll文件,不会加载与指定dll文件相关的dll文件,而LoadFrom则会加载与指定dll文件相关的dll文件 ///LoadFrom加载dll文件时会先检查前面是否已经加载过相同名称的dll,如果载入过相同的dll那就不能再载入,而LoadFile不检查,会直接覆盖之前相同名称的dll文件 /// /// foreach (var type in assembly2.GetTypes()) { Console.WriteLine("类:" + type.Name); foreach (var method in type.GetMethods()) { Console.WriteLine(type.Name + "类中的方法:" + method.Name); } } } #endregion #region 加载DLL并创建对象 { Console.WriteLine("*****************加载DLL并创建对象、调用方法********************"); Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); //1 动态加载 Type type = assembly.GetType("Gs.DB.SqlServer.SqlServerHelper"); //2 获取程序集下的指定类 foreach (var member in type.GetMembers()) { //遍历类中的方法 Console.WriteLine("方法名:" + member.Name); } //object oDBHelper = Activator.CreateInstance(type); //创建对象 //oDBHelper.Say(); //调用方法,实际上oDBHelper是有SqlServerHelper()这个方法,只不过编译器不通过,解决这个问题可以用dynamic来收 dynamic dDBHelper = Activator.CreateInstance(type); dDBHelper.Say(); //dynamic编译器不检查,方法拼写一定要写对 //不使用dynamic,转换类型也可以 object oDBHelper = Activator.CreateInstance(type); //创建对象 IDBHelper SqlServerHelper = oDBHelper as IDBHelper; SqlServerHelper.Say(); //调用方法,实际上oDBHelper是有SqlServerHelper()这个方法,只不过编译器不通过,解决这个问题可以用dynamic来收 } #endregion 封装之后 { Console.WriteLine("*****************封装之后********************"); IDBHelper iDBHelper = SimpleFactory.CreateInstance(); iDBHelper.Say(); //程序的可配置,通过修改配置文件就可以自动切换,实现类必须是事先已有的,而且在目录下面,没有写死类型,而是通过配置文件执行,反射创建的 //可扩展:完全不修改原有代码,只是增加新的实现,copy,修改配置文件,就可以支持新功能 //反射的动态加载和动态创建对象 以及配置文件结合 } #region 调用带参方法 { //Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer"); //Type type = assembly.GetType("Ruanmou.DB.SqlServer.ReflectionTest"); //foreach (ConstructorInfo ctor in type.GetConstructors()) //{ // Console.WriteLine(ctor.Name); // foreach (var parameter in ctor.GetParameters()) // { // Console.WriteLine(parameter.ParameterType); // } //} //object oTest1 = Activator.CreateInstance(type); //object oTest2 = Activator.CreateInstance(type, new object[] { 123 }); //object oTest3 = Activator.CreateInstance(type, new object[] { "陌殇" }); Console.WriteLine("*****************调用带参方法********************"); Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); Type type = assembly.GetType("Gs.DB.SqlServer.ReflectionTest"); foreach (ConstructorInfo ctor in type.GetConstructors()) { //获取类中的构造方法 Console.WriteLine("111:" + ctor.Name); foreach (var parameter in ctor.GetParameters()) { //返回构造方法的参数 Console.WriteLine("222:" + parameter.ParameterType); } } object oTest1 = Activator.CreateInstance(type); object oTest2 = Activator.CreateInstance(type, new object[] { 960927 }); object oTest3 = Activator.CreateInstance(type, new object[] { "调用带参方法" }); } #endregion #region 反射破坏单例 { Console.WriteLine("********************反射破坏单例********************"); 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)}"); //反射破坏单例---因为构造方法是用private修饰的,防止外部调用,但是反射不受限制 Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); Type type = assembly.GetType("Gs.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)}"); } #endregion 反射调用泛型 { Console.WriteLine("********************反射调用泛型********************"); Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); Type type = assembly.GetType("Gs.DB.SqlServer.GenericClass`3"); //3表示GenericClass有3个参数 Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) }); dynamic oGeneric = Activator.CreateInstance(typeMake); oGeneric.ShowA(); //MethodInfo method = type.GetMethod("Show").MakeGenericMethod(typeof(string), typeof(string), typeof(string)); //method.Invoke(oGeneric, new object[] { "123","456","789" }); } #region 做类型转换调用 { //如果反射创建对象之后,知道方法名称,怎么样不做类型转换,直接调用方法? //反射创建了对象实例---有方法的名称--反射调用方法 //dll名称---类型名称---方法名称---我们就能调用方法 //MVC就是靠的这一招---调用Action //http://localhost:9099/home/index 经过路由解析---会调用--HomeController--Index方法 //浏览器输入时只告诉了服务器类型名称和方法名称,肯定是反射的 //MVC在启动时会先加载--扫描全部的dll--找到全部的Controller--存起来--请求来的时候,用Controller来匹配的---dll+类型名称 //1 MVC局限性的--Action重载--反射是无法区分---只能通过HttpMethod+特性httpget/httppost //2 AOP--反射调用方法,可以在前后插入逻辑 Console.WriteLine("********************不做类型转换调用********************"); Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); Type type = assembly.GetType("Gs.DB.SqlServer.ReflectionTest"); object oTest = Activator.CreateInstance(type); foreach (var method in type.GetMethods()) { //获取类中的方法名 Console.WriteLine("方法名:" + method.Name); foreach (var parameter in method.GetParameters()) { //获取方法中的参数 Console.WriteLine(method.Name + "方法中的参数:" + parameter.Name + "===" + parameter.ParameterType); } } { ReflectionTest reflection = new ReflectionTest(); Console.WriteLine("普通调用"); reflection.Show1(); } { MethodInfo method = type.GetMethod("Show1"); Console.WriteLine("反射调用"); method.Invoke(oTest, null); } { MethodInfo method = type.GetMethod("Show2"); Console.WriteLine("反射调用有参方法"); method.Invoke(oTest, new object[] { 123 }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { }); Console.WriteLine("反射调用重载无参方法Show3"); method.Invoke(oTest, null); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) }); method.Invoke(oTest, new object[] { 1700 }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) }); method.Invoke(oTest, new object[] { "2020年2月23日17:02:00" }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) }); method.Invoke(oTest, new object[] { 1702, "2020年2月23日17:02:38" }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) }); method.Invoke(oTest, new object[] { "2020年2月23日17:04:02", 1704 }); } { MethodInfo method = type.GetMethod("Show5"); method.Invoke(oTest, new object[] { "2020年2月23日17:04:32" }); } } #endregion 调用私有方法 { //调用私有方法 Console.WriteLine("&&&&&&&&&&&&&&&&&&&&私有方法&&&&&&&&&&&&&&&&&&&"); Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); Type type = assembly.GetType("Gs.DB.SqlServer.ReflectionTest"); object oTest = Activator.CreateInstance(type); var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic); //var method = type.GetMethod("Show4"); method.Invoke(oTest, new object[] { "2020年2月23日17:13:08" }); } #region { Console.WriteLine("********************调用泛型方法********************"); Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); Type type = assembly.GetType("Gs.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[] { 1920, "2020年2月23日19:20:25", DateTime.Now }); } #endregion { Console.WriteLine("********************调用泛型类中的泛型方法********************"); Assembly assembly = Assembly.Load("Gs.DB.SqlServer"); Type type = assembly.GetType("Gs.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[] { 1927, "2020年2月23日19:42:22", DateTime.Now }); } #region { Console.WriteLine("*****************Common*******************"); People people = new People(); people.Id = 001; people.Name = "孙悟空"; people.Description = "我是齐天大圣"; Console.WriteLine($"people.Id={people.Id}"); Console.WriteLine($"people.Name={people.Name}"); Console.WriteLine($"people.Description={people.Description}"); } #endregion 反射赋值 { //1 get 反射展示是有意义的--反射遍历,可以不用改代码 //2 set 感觉好像没啥用 Console.WriteLine("*****************反射赋值*******************"); Type type = typeof(People); object oPeople = Activator.CreateInstance(type); foreach (var prop in type.GetProperties()) { Console.WriteLine("类:" + type.Name + ";属性:" + prop.Name + ";值:" + prop.GetValue(oPeople)); Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(oPeople)}"); if (prop.Name.Equals("Id")) { prop.SetValue(oPeople, 234); } else if (prop.Name.Equals("Name")) { prop.SetValue(oPeople, "猪八戒"); } Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(oPeople)}"); } foreach (var field in type.GetFields()) { Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(oPeople)}"); if (field.Name.Equals("Description")) { field.SetValue(oPeople, "我是天蓬元帅"); } Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(oPeople)}"); } } #region 动态查询数据库 { Console.WriteLine("******************动态查询数据库*********************"); SqlServerHelper helper = new SqlServerHelper(); Company company = helper.Find <Company>(1); User user = helper.Find <User>(1); } #endregion 测试性能 { Console.WriteLine("*******************测试性能*******************"); Monitor.Show(); } #region #endregion } catch (Exception e) { Console.WriteLine("错误信息:" + e.Message); } Console.WriteLine("运行完毕"); Console.ReadLine(); }
static void Main(string[] args) { try { #region Common { Console.WriteLine("*************** Common *****************"); IDBHelper iDBHelper = new MySqlHelper(); iDBHelper.Query(); } #endregion #region Reflection { Console.WriteLine("************* Reflection ***************"); Assembly assembly1 = Assembly.Load("Reflection.DB.MySql"); // 1 动态加载 一个完整的 dll 名称不需要后缀(从 exe 所在的路径进行查找) // Assembly assembly2 = Assembly.LoadFile(@"E:\GitHub\csharp\02Reflection\Reflection.DB.MySql\bin\Debug\netstandard2.0\Reflection.DB.MySql.dll"); // 必须要完整路径 // Assembly assembly3 = Assembly.LoadFrom("Reflection.DB.MySql.dll"); // 当前路径 // Assembly assembly4 = Assembly.LoadFrom(@"E:\GitHub\csharp\02Reflection\Reflection.DB.MySql\bin\Debug\netstandard2.0\Reflection.DB.MySql.dll"); //完整路径 foreach (var type in assembly1.GetTypes()) { Console.WriteLine(type.Name); foreach (var method in type.GetMethods()) { Console.WriteLine(method.Name); } } } #endregion { Assembly assembly = Assembly.Load("Reflection.DB.MySql"); // 1 动态加载 Type type = assembly.GetType("Reflection.DB.MySql.MySqlHelper"); // 2 获取类型 完整类型名称 object oDBHelper = Activator.CreateInstance(type); // 3 创建对象 // oDBHelper.Query(); // 无法直接调用方法,编译器不允许 // C# 是一种强类型语言,静态语言,编译时就确定好类型保证安全 dynamic dDBHelper = Activator.CreateInstance(type); dDBHelper.Query(); // dynamic 跳过编译器检查,运行时才检查 IDBHelper iDBHelper = oDBHelper as IDBHelper; // 4 类型转换 不报错,类型不对就返回 null iDBHelper.Query(); // 5 方法调用 } { Console.WriteLine("**** Reflection + Factory + Config ****"); IDBHelper iDBHelper = SimpleFactory.CreaterInstance(); iDBHelper.Query(); // 程序是可配置的,通过修改配置就可以自动切换 // 没有写死类型,而是通过配置文件执行,反射创建的 // 实现类必须是事先已有的,而且在目录下面 // 可扩展:完全不修改原有代码,只是增加新的实现、复制、修改配置,则可以支持新功能 // 反射的动态加载和动态创建对象,以及配置文件结合 } { Console.WriteLine("********* ctor + parameter **********"); Type type = Assembly.Load("Reflection.DB.SqlServer") .GetType("Reflection.DB.SqlServer.ReflectionTest"); IDBHelper iDBHelper1 = Activator.CreateInstance(type) as IDBHelper; IDBHelper iDBHelper2 = Activator.CreateInstance(type, new object[] { 123 }) as IDBHelper; IDBHelper iDBHelper3 = Activator.CreateInstance(type, new object[] { "oTest" }) as IDBHelper; foreach (ConstructorInfo ctor in type.GetConstructors()) { Console.WriteLine(ctor.Name); foreach (var parameter in ctor.GetParameters()) { Console.WriteLine(parameter.ParameterType); } } } { Console.WriteLine("************ Singleton *************"); Singleton singleton = Singleton.GetInstance(); Singleton singleton1 = Singleton.GetInstance(); Console.WriteLine(ReferenceEquals(singleton, singleton1)); Type type = Assembly.Load("Reflection.DB.SqlServer") .GetType("Reflection.DB.SqlServer.Singleton"); //Singleton singletonA = Activator.CreateInstance(type) as Singleton; // error: 无法实例化单例 // 反射破坏单例 —— 就是反射调用私有构造函数 Singleton singletonA = Activator.CreateInstance(type, true) as Singleton; Singleton singletonB = Activator.CreateInstance(type, true) as Singleton; Console.WriteLine(ReferenceEquals(singletonA, singletonB)); } { Console.WriteLine("********** GenericClass ***********"); Type type = Assembly.Load("Reflection.DB.SqlServer") .GetType("Reflection.DB.SqlServer.GenericClass`3"); // object oGeneric = Activator.CreateInstance(type); // error: 泛型无法直接实例化 Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) }); object oGeneric = Activator.CreateInstance(typeMake); } #region 泛型方法 { Console.WriteLine("********** GenericMethod ***********"); Type type = Assembly.Load("Reflection.DB.SqlServer") .GetType("Reflection.DB.SqlServer.GenericMethod"); object oGeneric = Activator.CreateInstance(type); foreach (MethodInfo item in type.GetMethods()) { Console.WriteLine(item.Name); } MethodInfo method = type.GetMethod("Show"); MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) }); methodNew.Invoke(oGeneric, new object[] { 123, "John", DateTime.Now }); } { Console.WriteLine("******* GenericClass&Method ********"); Type type = Assembly.Load("Reflection.DB.SqlServer") .GetType("Reflection.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[] { 123, "John", DateTime.Now }); } #endregion { // 反射创建对象后,知道方法名称,可以直接调用而不需做类型转换 // 反射创建了对象实例——知道方法的名称——反射调用方法 // dll 名称——类型名称——方法名称——我们就能调用方法 // MVC 依赖这种模式——调用 Action // http://localhost:9099/home/index 通过路由解析——会调用 HomeController——Index方法 // 相当于浏览器输入时告诉了服务器类型的名称和方法的名称 // MVC 加载时会先扫描所有 dll —— 找到所有的控制器 —— 请求来时用Controller 来匹配 // 1 MVC的局限性:Action 重载时,反射是无法区分的,只能通过 HttpMethod + 特性 HttpGet/HttpPost 等 // 2 AOP 反射调用方法,可以在前后插入逻辑 Console.WriteLine("********** GenericMethod ***********"); Type type = Assembly.Load("Reflection.DB.SqlServer") .GetType("Reflection.DB.SqlServer.ReflectionTest"); object oTest = Activator.CreateInstance(type); // 直接调用 Show1 方法 foreach (var method in type.GetMethods()) { Console.WriteLine(method.Name); foreach (var parameter in method.GetParameters()) { Console.WriteLine($"{parameter.Name} {parameter.ParameterType}"); } } { MethodInfo method = type.GetMethod("Show1"); method.Invoke(oTest, null); } { MethodInfo method = type.GetMethod("Show2"); method.Invoke(oTest, new object[] { 123 }); } { 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[] { "John" }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) }); method.Invoke(oTest, new object[] { 123, "John" }); } { MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) }); method.Invoke(oTest, new object[] { "John", 123 }); } { // 静态方法实例可要可不要 MethodInfo method = type.GetMethod("Show5"); method.Invoke(oTest, new object[] { "John" }); method.Invoke(null, new object[] { "John" }); } } #region 反射调用私有方法 { Console.WriteLine("********* 反射调用私有方法 *********"); Type type = Assembly.Load("Reflection.DB.SqlServer") .GetType("Reflection.DB.SqlServer.ReflectionTest"); object oTest = Activator.CreateInstance(type); var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic); object oReturn = method.Invoke(oTest, new object[] { "John" }); } #endregion #region { } #endregion } catch (Exception) { throw; } }