乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      C#反射

       路人甲Java 2021-03-14

      1.What?反射是什么?

      反射:無處不在,MVC,Webfrom,asp.net,ORM,IOC,AOP,幾乎所有的框架都離不開反射,那么反射到底是什么?

      我們寫的代碼,計(jì)算機(jī)要識(shí)別,需要二次編譯,中間會(huì)經(jīng)過編譯器編譯,得到dll,exe,再被JIT編譯最終被計(jì)算機(jī)語言識(shí)別,執(zhí)行,那dll,exe是怎么生成的呢?

      生成的exe還可以直接打開執(zhí)行

       那這個(gè)exe里面具體是什么呢?我們可以用反編譯工具打開看看,打開就可以看到我們反編譯以后的IL:也是一種面向?qū)ο笳Z言,但是不太好閱讀

      反射Reflection:system.Reflection,其實(shí)就是.net.fromwork提供的一個(gè)幫助內(nèi)庫,可以讀取并使用metadata

      那我們?nèi)绾稳?/span>讀取信息呢?

      2.用反射加載和讀取信息[三種方式]

      我們先隨便寫個(gè)接口類:新建-DB.Interface類庫,新建一個(gè)接口類IDBHelper

       1 using System;
       2 using System.Collections.Generic;
       3 using System.Linq;
       4 using System.Text;
       5 using System.Threading.Tasks;
       6 
       7 namespace DB.Interface
       8 {
       9     // DB.Interface接口類庫
      10     public interface IDBHelper
      11     {
      12         void Query();
      13     }
      14 }

      再新建一個(gè)DB.MySql類庫,新建一個(gè)MySqlHelper類繼承接口IDBHelper

      using DB.Interface;
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace DB.MySql
      {
          public class MySqlHelper : IDBHelper
          {
              /// <summary>
              /// MySqlHelper構(gòu)造函數(shù)
              /// </summary>
              public MySqlHelper()
              {
                  Console.WriteLine("{0}被構(gòu)造", this.GetType().Name);
              }
              /// <summary>
              /// Query方法
              /// </summary>
              public void Query()
              {
                  Console.WriteLine("{0}.Query",this.GetType().Name);
              }
          }
      }
      MySqlHelper

      按照上面的步驟,新建一個(gè)DB.SqlServer類庫,新建一個(gè)SqlServerHelper類繼承接口IDBHelper

      using DB.Interface;
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace DB.SqlServer
      {
          /// <summary>
          /// SqlServer實(shí)現(xiàn)
          /// </summary>
          public class SqlServerHelper : IDBHelper
          {
              /// <summary>
              /// SqlServerHelper構(gòu)造函數(shù)
              /// </summary>
              public SqlServerHelper()
              {
                  Console.WriteLine("{0}被構(gòu)造",this.GetType().Name);
              }
              /// <summary>
              /// Query方法
              /// </summary>
              public void Query()
              {
                  Console.WriteLine("{0}.Query",this.GetType().Name);
              }
          }
      }
      SqlServerHelper
                      #region Reflecgion
                      {
                          Console.WriteLine("---------------------------------------------反射加載和讀取信息---------------------------------------------------------");
                          //動(dòng)態(tài)加載 都是把dll加到內(nèi)存里面去,不需要向上面的普通方法一樣引用
                          //1.一個(gè)完整的dll名稱,不需要后綴,目的:把dll加載到內(nèi)存中間去;
                          //缺陷:但是有個(gè)限制從編譯以后生成的exe所在的路徑去查找,既可以找dll,又可以找exe,兩個(gè)一樣得話先找dll【常用】
                          Assembly assembly = Assembly.Load("DB.MySql");
                          //2.還有一種加載方式,path,需要一個(gè)完整的路徑,性能差不多,也可以切換為別的引用了的路徑【全名稱= 全路徑+dll名稱 + 后綴】
                          Assembly assembly1 = Assembly.LoadFile(@"F:\LearnTest\MyReflectionFirst\MyReflectionFirst\bin\Debug\DB.MySql.dll");
                          //3.loadfrom:帶后綴的,當(dāng)前路徑查找,也可以全路徑
                          Assembly assembly2 = Assembly.LoadFrom("DB.MySql.dll");//【當(dāng)前路徑+ 后綴】
                          Assembly assembly3 = Assembly.LoadFrom(@"F:\LearnTest\MyReflectionFirst\MyReflectionFirst\bin\Debug\DB.MySql.dll");
      
                          //讀取里面的信息
                          foreach (var types in assembly.GetTypes())//GetTypes 獲取此程序集中的全部類型
                          {
                              Console.WriteLine(types.Name);
      //type.IsGenericType //判斷當(dāng)前是否是泛型類
      foreach (var method in types.GetMethods())//返回為GetMethods的所有公共方法 { Console.WriteLine(method.Name); } } } #endregion

       我們跟蹤就可以看到利用反射加載出來的一些基本信息

      3.反射使用信息

                      #region Common
                      {
                          Console.WriteLine("---------------------------------------------Common---------------------------------------------------------");
                          {
                              //添加接口引用,內(nèi)庫引用,實(shí)例化并且調(diào)用方法
                              IDBHelper dBHelper = new MySqlHelper();
                              dBHelper.Query();
                          }
                      }
                      #endregion
                      #region Reflecgion
                      {
                          Console.WriteLine("---------------------------------------------用反射使用信息---------------------------------------------------------");
                          //1.動(dòng)態(tài)加載
                          Assembly assembly = Assembly.Load("DB.MySql");
                          // 第一步我們會(huì)獲取到全部的類型,也可以指定獲取類型【完整類型名稱】
                          Type type = assembly.GetType("DB.MySql.MySqlHelper");
                          //3.實(shí)例化
                           // 意思跟Activator.CreateInstance(type);差不多都是實(shí)例化new MySqlHelper();但是這邊創(chuàng)建的實(shí)例是個(gè)object類型
                          object oDBHelper=Activator.CreateInstance(type);
                          //很確定oDBHelper里面有Query這個(gè)方法Why不能直接調(diào)用方法?編譯器不認(rèn)可,不能直接調(diào)用
                          //c#是一門強(qiáng)類型語言,靜態(tài)語言,編譯時(shí)就確定好了類型確保安全
                          //oDBHelper.Query()
                          //dynamic可以是因?yàn)樗芴厥饩幾g器不檢查,運(yùn)行時(shí)才檢查
                          //dynamic dDBHelper = Activator.CreateInstance(type);
                          //dDBHelper.Query();
      
                          //4.類型轉(zhuǎn)換,類型不對(duì)會(huì)直接返回null
                          IDBHelper dBHelper = oDBHelper as IDBHelper;
                          //5.方法調(diào)用
                          dBHelper.Query();
                      }
                      #endregion

      那么問題來了我只需要用普通方法兩句話寫完的,我們?yōu)槭裁匆梅瓷湟獙?句???何必呢?意義何在?

      我們就上面的代碼先來封裝一下看看:

      1 <configuration>
      2     <startup> 
      3         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
      4     </startup>
      5     <appSettings>
      6         <!--以英文逗號(hào)","分開-->
      7         <add key="IDBHelperConfig" value="DB.MySql.MySqlHelper,DB.MySql"/>
      8 </configuration>
      namespace MyReflectionFirst
      {
          public class SingleFactory
          {
              /// <summary>
              /// private避免被人可以看到,static靜態(tài),會(huì)在程序第一次調(diào)用的時(shí)候讀取,只讀一遍
              /// </summary>
              private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"].ToString();
              private static string TypeName = IDBHelperConfig.Split(',')[0];
              private static string DLLName = IDBHelperConfig.Split(',')[1];
              public static IDBHelper CreateInstance()
              {
                  Assembly assembly = Assembly.Load(DLLName);
                  Type type = assembly.GetType(TypeName);
                  object oDBHelper = Activator.CreateInstance(type);
                  IDBHelper dBHelper = oDBHelper as IDBHelper;
                  return dBHelper;
              }
          }
      }

      那我們?cè)賮碚{(diào)用看看:

                      {
                          Console.WriteLine("-------------------------------------Reflecgion+Factory+Config-------------------------------------------------");
                          IDBHelper dBHelper = SingleFactory.CreateInstance();
                          dBHelper.Query();
                      }

      這是普通方法和反射封裝完成調(diào)用 的結(jié)果以及代碼對(duì)比,從調(diào)用上是不是差不多了呢?

      我們?cè)龠M(jìn)一步對(duì)比延伸擴(kuò)展一下:

      如果我們需要更換一下版本呢?

      普通方法:【就必須重新引用,修改代碼,重新編譯發(fā)布

                              //如果從MySqlHelper換成SqlServerHelper,就必須重新引用,修改代碼,重新編譯發(fā)布
                              IDBHelper dBHelper = new SqlServerHelper();
                              dBHelper.Query();

      而我們的反射,只需修改配置文件即可:

                            <add key="IDBHelperConfig" value="DB.SqlServer.SqlServerHelper,DB.SqlServer"/>

       結(jié)果:

      那要是我們要新增一個(gè)以前沒有的Oracle版本:

      按照上面的步驟,新建一個(gè)DB.Oracle類庫,新建一個(gè)OracleHelper類繼承接口IDBHelper

      using DB.Interface;
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace DB.Oracle
      {
          public class OracleHelper : IDBHelper
          {
              public OracleHelper() 
              {
                  Console.WriteLine("{0}被構(gòu)造",this.GetType().Name);
              }
              public void Query()
              {
                  Console.WriteLine("{0}.Query",this.GetType().Name);
              }
      
          }
      }
      OracleHelper

       用反射,通過修改配置文件就可以達(dá)到以下結(jié)果:

                        <add key="IDBHelperConfig" value="DB.Oracle.OracleHelper,DB.Oracle"/>

      結(jié)果:

      //特點(diǎn):動(dòng)態(tài)擴(kuò)展性太強(qiáng)
      //可配置可擴(kuò)展:完全不修改原有代碼,只是增加新的實(shí)現(xiàn),copy,修改配置文件,就可以支持新功能
      //原理:反射的動(dòng)態(tài)加載和動(dòng)態(tài)創(chuàng)建對(duì)象,以及配置文件結(jié)合
      //可以支持隨機(jī)換,也可以后面新增
      //前提:實(shí)現(xiàn)類必須是事先已有的,而且在目錄下面的

      4.反射的使用

      上面我們用反射獲取了無參數(shù)的構(gòu)造函數(shù),那么我們?cè)趺慈カ@取有參數(shù)的構(gòu)造函數(shù)呢?我們?cè)趺慈カ@取構(gòu)造函數(shù)參數(shù),以及類型,調(diào)用?

       讓我們看一個(gè)例子,在DB.SqlServer類庫中,新建一個(gè)ReflecgionTest類

          public class ReflecgionTest
          {
              #region Identity
              public ReflecgionTest()
              {
                  Console.WriteLine("這是{0}無參數(shù)構(gòu)造函數(shù)", this.GetType());
              }
              public ReflecgionTest(string name)
              {
                  Console.WriteLine("這是{0}有參數(shù)構(gòu)造函數(shù)", this.GetType());
              }
              public ReflecgionTest(int id)
              {
                  Console.WriteLine("這是{0}有參數(shù)構(gòu)造函數(shù)", this.GetType());
              }
              #endregion
          }
                      {
                          Console.WriteLine("-----------------------------------ctor&parameter---------------------------------------------------");
                          Assembly assembly = Assembly.Load("DB.SqlServer");
                          Type type = assembly.GetType("DB.SqlServer.ReflecgionTest");
                          //獲取構(gòu)造函數(shù)
                          foreach (ConstructorInfo ctor in type.GetConstructors())//循環(huán)訪問集合或數(shù)組的名稱
                          {
                              Console.WriteLine(ctor.Name);
                              //獲取構(gòu)造函數(shù)參數(shù)
                              foreach (var parameter in ctor.GetParameters())
                              {
                                  //獲取構(gòu)造函數(shù)參數(shù)類型
                                  Console.WriteLine(parameter.ParameterType);
                              }
                          }
      
                          //怎么為不同的構(gòu)造函數(shù)指定不同的參數(shù)類型
                          //object test1 = Activator.CreateInstance(type);
                          //object test2 = Activator.CreateInstance(type, "123");
                          //object test3 = Activator.CreateInstance(type, 123);
                          //應(yīng)用建議改為以下寫法
                          object test4 = Activator.CreateInstance(type, new object[] { "123" });
                          object test5= Activator.CreateInstance(type, new object[] { 123});
                      }

      結(jié)果:

      5.反射-黑科技:反射破壞單例

      讓我們看一個(gè)例子,在DB.SqlServer類庫中,新建一個(gè)Singleton類

      namespace DB.SqlServer
      {
          /// <summary>
          /// 單例模式:就是一個(gè)類,保證在整個(gè)進(jìn)程中就只有一個(gè)實(shí)例
          /// </summary>
          public sealed class Singleton
          {
              //3.當(dāng)然這個(gè)實(shí)例只能有一個(gè),所以我們提供了一個(gè)靜態(tài)字段,
              private static Singleton _singleton = null;
              //1.構(gòu)造函數(shù)私有化,才不能隨便new,才能保證只有一個(gè)對(duì)象
              private Singleton()
              {
                  Console.WriteLine("{0}被構(gòu)造",this.GetType().Name);
              }
              //4.這個(gè)字段只能初始化一次,那怎么初始化?我們交給了這個(gè)靜態(tài)構(gòu)造函數(shù),它由CLR保障,在程序啟動(dòng)的第一次調(diào)用這個(gè)類Singleton之前完成的調(diào)用,而且只調(diào)用一次
              static Singleton()
              {
                  _singleton = new Singleton();
              }
              //2.私有化了之后,對(duì)外不能new,但我可以對(duì)外提供一個(gè)公開的靜態(tài)方法,負(fù)責(zé)提供這個(gè)對(duì)象的實(shí)例,可以調(diào)用這個(gè)方法獲取這個(gè)實(shí)例,那怎么獲???
              public static Singleton GetInstance()
              {
                  return _singleton;
              }
          }
      }
                      {
                          Console.WriteLine("-----------------------------------擴(kuò)展:未使用反射之前的單例調(diào)用---------------------------------------------------");
                          //Singleton singleton = new Singleton();//私有化不能直接構(gòu)造
                          Singleton singleton1 = Singleton.GetInstance();
                          Singleton singleton2 = Singleton.GetInstance();
                          Singleton singleton3 = Singleton.GetInstance();
                          Console.WriteLine($"{Object.ReferenceEquals(singleton1, singleton3)}");//不管有幾個(gè)實(shí)例,結(jié)果肯定為True,因?yàn)槎际峭粋€(gè)對(duì)象,只會(huì)被構(gòu)造一次
                      }
                      {
                          Console.WriteLine("-----------------------------------擴(kuò)展:反射破壞單例---反射調(diào)用私有構(gòu)造函數(shù)---------------------------------------------------");
                          Assembly assembly = Assembly.Load("DB.SqlServer");
                          Type type = assembly.GetType("DB.SqlServer.Singleton");
                          //Singleton singletonA=(Singleton)Activator.CreateInstance(type);//類型轉(zhuǎn)換
                          //如上寫法會(huì)報(bào)錯(cuò),因?yàn)樯厦嫖覀冋f過它相當(dāng)于一個(gè)實(shí)例化,但是這個(gè)構(gòu)造函數(shù)私有化,不能直接New
                          Singleton singletonA = (Singleton)Activator.CreateInstance(type,true);//但是反射做到了這件事
                          //Why這個(gè)地方執(zhí)行了第一次使用的時(shí)候會(huì)執(zhí)行兩遍構(gòu)造函數(shù),程序在一次使用這個(gè)類的時(shí)候就會(huì)去完成靜態(tài)構(gòu)造函數(shù)的構(gòu)造,程序在每次使用都會(huì)再去構(gòu)造一次
                          Singleton singletonB = (Singleton)Activator.CreateInstance(type, true);
                          Singleton singletonC = (Singleton)Activator.CreateInstance(type, true);
                          //nonPublic:如果公共或非公共默認(rèn)構(gòu)造函數(shù)可以匹配,則為true;如果只有公共默認(rèn)構(gòu)造函數(shù)可以匹配,則為false。
                          //所以對(duì)象是不一樣的,對(duì)象被構(gòu)造了多次
                          Console.WriteLine($"{Object.ReferenceEquals(singletonA,singletonC)}");
      
                      }

      結(jié)果對(duì)比:

       六.反射調(diào)用泛型類與方法

      讓我們看一個(gè)例子,在DB.SqlServer類庫中,新建一個(gè)GenericTest類

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace DB.SqlServer
      {
          public class GenericTest<T,W,X>
          {
              public void Show(T t, W w,X x)
              {
                  Console.WriteLine("This's 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("This's t.type={0},w.type={1}, x.type={2},t:{3},w:{4},x:{5}", t.GetType().Name, w.GetType().Name, x.GetType().Name, t, w, x);
              }
          }
          public class GenericDouble<T>
          {
              public void Show<W, X>(T t, W w, X x)
              {
                  Console.WriteLine("This's t.type={0},w.type={1}, x.type={2},t:{3},w:{4},x:{5}", t.GetType().Name, w.GetType().Name, x.GetType().Name,t,w,x);
              }
          }
      }
      泛型
                      {
                          Console.WriteLine("-----------------------------------擴(kuò)展:反射和泛型---------------------------------------------------");
                          Assembly assembly = Assembly.Load("DB.SqlServer");
                          Type type = assembly.GetType("DB.SqlServer.GenericTest");
                          Object oGeneric = Activator.CreateInstance(type);
                      }

      按照之前的操作,我們發(fā)現(xiàn)這邊得到的type=null?Why?

      //原因:因?yàn)閜ublic class GenericTest<T,W,X>它是泛型編譯之后會(huì)變?yōu)镈B.SqlServer.GenericTest`3<T, W, X>【反編譯工具也可以看到】

      // 我們需要把它修改為:
      Type type = assembly.GetType("DB.SqlServer.GenericTest`3");

      跟蹤結(jié)果已經(jīng)找到了我們要的數(shù)據(jù)了:

       再執(zhí)行,報(bào)錯(cuò)了,類型找到了,為什么它不能創(chuàng)建這個(gè)實(shí)例?它不是有個(gè)無參數(shù)構(gòu)造函數(shù)嗎?為什么沒能創(chuàng)建一個(gè)實(shí)例?

       那這代碼現(xiàn)在應(yīng)該如何修改呢?

                          //在泛型類型時(shí),不能忘記我們創(chuàng)建對(duì)象,它是不能夠?qū)嵗?【eg:GenericTest genericTest=new GenericTest()】那肯定是不行的
                          //起碼你得指定好類型才能夠?qū)嵗緀g:GenericTest<int, string, DateTime> genericTest = new GenericTest<int, string, DateTime>();】那應(yīng)該怎樣寫呢?
                          Type typeMake = type.MakeGenericType(new Type[] {typeof(int),typeof(string),typeof(DateTime) });
                          //泛型類是一個(gè)不確定類型的,這句話就表示我把類型確定一下,你要什么參數(shù)類型,這邊是個(gè)type數(shù)組,new Type[] {}數(shù)組
                          Object oGeneric = Activator.CreateInstance(typeMake);//只有這個(gè)typeMake才可以創(chuàng)建,這邊不能強(qiáng)制轉(zhuǎn)換,因?yàn)樾枰愋?/span>

      跟蹤的結(jié)果:

      如果反射創(chuàng)建對(duì)象之后,知道方法名稱,怎么樣不做類型轉(zhuǎn)換,直接調(diào)用方法?讓我們直接下面的實(shí)例吧

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace DB.SqlServer
      {
          public class ReflecgionTest
          {
              #region Identity
              public ReflecgionTest()
              {
                  Console.WriteLine("這是{0}無參數(shù)構(gòu)造函數(shù)", this.GetType());
              }
              public ReflecgionTest(string name)
              {
                  Console.WriteLine("這是{0}有參數(shù)構(gòu)造函數(shù)", this.GetType());
              }
              public ReflecgionTest(int id)
              {
                  Console.WriteLine("這是{0}有參數(shù)構(gòu)造函數(shù)", this.GetType());
              }
              #endregion
      
              #region Method
              /// <summary>
              /// 無參方法
              /// </summary>
              public void Show1()
              {
                  Console.WriteLine("這里是{0}的Show1", this.GetType());
              }
              /// <summary>
              /// 有參數(shù)方法
              /// </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,id:{1},string:{2}", this.GetType(),id,name);
              }
              /// <summary>
              /// 重載方法之二
              /// </summary>
              /// <param name="name"></param>
              /// <param name="id"></param>
              public void Show3(string name, int id)
              {
                  Console.WriteLine("這里是{0}的Show3_2,string:{1},id:{2}", this.GetType(),name,id);
              }
              /// <summary>
              /// 重載方法之三
              /// </summary>
              /// <param name="id"></param>
              public void Show3(int id)
              {
      
                  Console.WriteLine("這里是{0}的Show3_3,id:{1}", this.GetType(),id);
              }
              /// <summary>
              /// 重載方法之四
              /// </summary>
              /// <param name="name"></param>
              public void Show3(string name)
              {
      
                  Console.WriteLine("這里是{0}的Show3_4,name:{1}", this.GetType(),name);
              }
              /// <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_私有方法調(diào)用", this.GetType());
              }
              /// <summary>
              /// 靜態(tài)方法
              /// </summary>
              /// <param name="name"></param>
              public static void Show5(string name)
              {
                  Console.WriteLine("這里是{0}的Show5_靜態(tài)方法調(diào)用", typeof(ReflecgionTest));
              }
              #endregion
          }
      }
      ReflecgionTest.cs

      反射調(diào)用:無參數(shù),有參數(shù),重載,靜態(tài),私有方法實(shí)例

                      {
                          Console.WriteLine("如果反射創(chuàng)建對(duì)象之后,知道方法名稱,怎么樣不做類型轉(zhuǎn)換,直接調(diào)用方法?");
                          Assembly assembly = Assembly.Load("DB.SqlServer");
                          Type type = assembly.GetType("DB.SqlServer.ReflecgionTest");
                          Object test = Activator.CreateInstance(type);
                          //主要是查看它里面的所有方法名,參數(shù),參數(shù)類型
                          foreach (var metohd in type.GetMethods())
                          {
                              Console.WriteLine(metohd.Name+"");
                              foreach (var parameter in metohd.GetParameters())
                              {
                                  Console.WriteLine($"{parameter.Name},{parameter.ParameterType.Name}");
                              }
                          }
                          //反射調(diào)用無參數(shù)的方法
                          {
                              MethodInfo methodInfo = type.GetMethod("Show1");
                              methodInfo.Invoke(test, null);//第一個(gè)參數(shù)表示實(shí)例,后一個(gè)參數(shù)列表
                          }
                          //反射調(diào)用帶參數(shù)的方法
                          {
                              MethodInfo methodInfo1 = type.GetMethod("Show2");
                              methodInfo1.Invoke(test, new object[] { 123 });
                          }
                          //重載方法調(diào)用
                          {
                              MethodInfo method=type.GetMethod("Show3",new Type[] { typeof(string),typeof(int)});
                              method.Invoke(test, new object[] { "現(xiàn)在是哪一年", 2020});
                          }
                          {
                              MethodInfo method = type.GetMethod("Show3",new Type[] { typeof(int),typeof(string)});
                              method.Invoke(test, new object[] { 2020, "year" });
                          }
                          {
                              MethodInfo method = type.GetMethod("Show3",new Type[] { typeof(int)});
                              method.Invoke(test, new object[] { 2020 });
                          }
                          {
                              MethodInfo method = type.GetMethod("Show3",new Type[] { typeof(string)});
                              method.Invoke(test, new object[] { "wang" });
                          }
                          {
                              MethodInfo method = type.GetMethod("Show3",new Type[] { });
                              method.Invoke(test, null);
                          }
                          //靜態(tài)方法【特別】:實(shí)例可以要,也可以不要【null】
                          {
                              MethodInfo method = type.GetMethod("Show5");
                              method.Invoke(null,new object[] { "你好"});
                          }
                          {
                              MethodInfo method = type.GetMethod("Show5");
                              method.Invoke(test, new object[] { "你好" });
                          }
                          {//反射調(diào)用私有方法
                              var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
                              method.Invoke(test, new object[] { "私有方法調(diào)用" });
                          }
                      }

      結(jié)果:

        那么泛型的方法又如何用反射調(diào)用呢?

                      {
                          Console.WriteLine("-----------------------------------擴(kuò)展:泛型方法GenericMethod---------------------------------------------------");
                          Assembly assembly = Assembly.Load("DB.SqlServer");
                          Type type = assembly.GetType("DB.SqlServer.GenericMethod");
                          Object oGeneric = Activator.CreateInstance(type);
                          MethodInfo method = type.GetMethod("Show");//泛型方法不用Show`3
                          var methodnew=method.MakeGenericMethod(new Type[]{ typeof(int),typeof(string), typeof(DateTime)});
                          methodnew.Invoke(oGeneric, new object[] { 12, "泛型方法 ", DateTime.Now });
                      }

      結(jié)果:

      泛型方法和泛型類同時(shí)存在的情況:

                      {
                          Console.WriteLine("擴(kuò)展:泛型類+泛型方法GenericMethod");
                          Assembly assembly = Assembly.Load("DB.SqlServer");
                          Type type = assembly.GetType("DB.SqlServer.GenericDouble`1").MakeGenericType(new Type[] { typeof(int) });
                          Object oObject=Activator.CreateInstance(type);
                          MethodInfo method = type.GetMethod("Show").MakeGenericMethod(new Type[] {typeof(string),typeof(DateTime) });
                          method.Invoke(oObject,new object[] { 2020,"hello",DateTime.Today});
                      }

      結(jié)果:

       七:反射的應(yīng)用:

      獲取全部的實(shí)體的全部屬性并給其賦值:

      //實(shí)體類不考慮擴(kuò)展問題,沒意義
                          Console.WriteLine("---------------------------------------------Reflection---------------------------------------------------------");
                          Type type = typeof(People);
                          Object opeople=Activator.CreateInstance(type);
                          //獲取全部的屬性
                          foreach (var prop in type.GetProperties())
                          {
                              Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(opeople)}");
                              //給prop里面的屬性增加一個(gè)值
                              if (prop.Name.Equals("Id"))
                              {
                                  prop.SetValue(opeople, 1);
                              }
                              else if(prop.Name.Equals("Name"))
                              {
                                  prop.SetValue(opeople, "泛型實(shí)體屬性");
                              }
                              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, "只是一個(gè)字段");
                              }
                              Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(opeople)}");
                          }
      //思考:反射對(duì)實(shí)體層的操作如此麻煩,Why我們還要用它?eg:讓我們一起看一個(gè)場(chǎng)景:
              public Company FindOld(int Id)
              {
                  string sql = @"SELECT  [Id]
                                          ,[Name]
                                          ,[CreateTime]
                                          ,[CreatorId]
                                          ,[LastModifierId]
                                          ,[LastModifyTime]
                                          FROM [Company]
                                          where Id="+Id;
                  //[Name],[CreateTime],[CreatorId],[LastModifierId],[LastModifyTime],[Id]
                  using (SqlConnection con = new SqlConnection(ConnectionStringCustomers))
                  {
                      SqlCommand sqlCommand = new SqlCommand(sql, con);
                      con.Open();
                      var reader=sqlCommand.ExecuteReader();
                      if (reader.Read())//有數(shù)據(jù)才開始讀,有數(shù)據(jù)True
                      {
                          Console.WriteLine(reader[1]);
                      }
                      con.Close();
                      con.Dispose();
                  }
                  return new Company();
              }

      現(xiàn)在只有一個(gè)表,我們還有一個(gè)表,那如果我們有很多表,那豈不是都需要寫很多方法, 如果我們希望一個(gè)方法,能返回不同的類型,針對(duì)以上代碼優(yōu)化:

              /// <summary>
              ///  如果我們希望一個(gè)方法,能返回不同的類型?泛型+反射【不同類型,不同sql】,
              /// </summary>
              public T Find<T>(int Id)
              {
                  Type type = typeof(T);
      
                  //type.GetProperties().Select(p=> p.Name)得到屬性名稱,
                  //type.GetProperties().Select(p => $"[{p.Name}]")得到它的屬性名稱并寫出如下格式:[CreatorId]*/
                  //得到的是一個(gè)集合,需要把它變成一個(gè)逗號(hào)連接的字符串
      
                  //得到它的屬性名稱,把它變成一個(gè)逗號(hào)連接的字符串
                  string prop = string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"));
                  
                  //動(dòng)態(tài)拼接Sql
                  string sql = $"select {prop} from [{type.Name}] where ID={Id}";
                  Object oObject = Activator.CreateInstance(type);
                  //如果是User表User在數(shù)據(jù)庫里面屬于關(guān)鍵字,[{type.Name}]類似FROM [User]
                  using (SqlConnection con = new SqlConnection(ConnectionStringCustomers))
                  {
                      SqlCommand sqlCommand = new SqlCommand(sql, con);
                      con.Open();
                      var reader = sqlCommand.ExecuteReader();
                      if (reader.Read())//有數(shù)據(jù)才開始讀,有數(shù)據(jù)True
                      {
                          //獲取所有的屬性進(jìn)行賦值
                          foreach (var propinfo in type.GetProperties())
                          {
                              //針對(duì)數(shù)據(jù)庫名跟實(shí)力類名一一對(duì)應(yīng)的場(chǎng)景
                              propinfo.SetValue(oObject, reader[propinfo.Name] is DBNull ? null : reader[propinfo.Name]);
                          }
                          return (T)oObject;
                      }
                      else
                      {
                          return default;
                      }
                  }
                  
              }

      調(diào)用:

                      {
                          SqlServerHelper sqlServer = new SqlServerHelper();
                          Company company = sqlServer.Find<Company>(1);
                          User user = sqlServer.Find<User>(1);
                      }
                      {
                          Console.WriteLine("---------------------------------------------Common---------------------------------------------------------");
                          People people = new People();
                          people.Id = 1;
                          people.Name = "普通";
                          people.Description = "描述:";
                          Console.WriteLine($"people.Id ={people.Id}");
                          Console.WriteLine("people.Name = {0},people.Description={1}",people.Name,people.Description);
                      }
      //Get:反射展示是意義的,可以不用改代碼,普通方法需要修改
      //Set:感覺沒什么用,但是還是有用,
                          //反射:
                          //優(yōu)點(diǎn):動(dòng)態(tài),【幾乎任何一個(gè)框架里面都有反射,我們搭建框架就是希望有良好的擴(kuò)展性,能夠應(yīng)對(duì)將來任意的需求變化】
                          //缺點(diǎn);1.使用麻煩【封裝一下】;2.避開編譯器檢查,運(yùn)行時(shí)出問題;3.性能問題;
      using DB.Interface;
      using DB.SqlServer;
      using System;
      using System.Collections.Generic;
      using System.Diagnostics;
      using System.Linq;
      using System.Reflection;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace MyReflectionFirst
      {
          public class Monitor
          {
              public static void Show()
              {
                  Console.WriteLine("------------------------------Monitor普通方法與反射的性能測(cè)試--------------------------------------------");
                  //初始化
                  long ComonTime = 0;
                  long ReflectionTime = 0;
                  {
                      Stopwatch stopwatch = new Stopwatch();
                      stopwatch.Start();
                      for (int i = 0; i < 1_000_000; i++)
                      {
                          IDBHelper sqlServer = new SqlServerHelper();
                          sqlServer.Query();
                      }
                      stopwatch.Stop();
                      ComonTime = stopwatch.ElapsedMilliseconds;
                  }
                  {
                      Stopwatch stopwatch = new Stopwatch();
                      stopwatch.Start();
                      Assembly assembly = Assembly.Load("DB.SqlServer");
                      Type type = assembly.GetType("DB.SqlServer.SqlServerHelper");
                      for (int i = 0; i < 1_000_000; i++)
                      {
                          Object oDBHelper = Activator.CreateInstance(type);
                          IDBHelper dBHelper = oDBHelper as IDBHelper;
                          dBHelper.Query();
                      }
                      stopwatch.Stop();
                      ReflectionTime = stopwatch.ElapsedMilliseconds;
                  }
                  Console.WriteLine("ComonTime:{0}ms,ReflectionTime:{1}ms", ComonTime, ReflectionTime);
                  //ComonTime:71ms,ReflectionTime:134ms
              }
          }
      }
      Monitor普通方法與反射的性能測(cè)試

       

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多