<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      反射

      反射

      反射反射程序員的快樂,反射是無處不在的,封裝框架,系統開發(fā),MVC,IOC,ORM都離不開反射。

      一、反射/反編譯工具/高級語言到計算機語言的歷程

      1. 高級語言---編譯---dll/exe文件
      2. metadata:元數據清單---記錄了dll中包含哪些東西,是一個描述。
      3. IL:中間語言---編譯把高級語言編譯后得到c#中最真實的言語狀態(tài),面向對象語言。
      4. 反編譯工具:逆向工程;ILSPY --- DLL/EXE、 --- 反編譯回來,c#/IL
      5. 反射: 來自于System.Reflection,是一個幫助類庫---可以讀取DLL/EXE中metadata和使用metadata + 動態(tài)的創(chuàng)建dll/exe --- Emit技術

      二、反射創(chuàng)建對象

      首先定義一個接口

      namespace Business.DB.Interface
      {
          /// <summary>
          /// 數據訪問類抽象
          /// </summary>
          public interface IDBHelper
          {
              void Query();
          }
      }
      
      

      實現了接口的類

      namespace Business.DB.SqlServer
      {
          public class SqlServerHelper
          {
              //Nuget:System.Data.SqlClient
      
              private string ConnectionString = "Data Source=DESKTOP-VUL99EF; Database=CustomerDB; User ID=sa; Password=sa123; MultipleActiveResultSets=True";
      
              private static string GetConnection()
              {
                  //Nuget引入:
                  //SetBasePath:Microsoft.Extensions.Configuration.FileExtensions
                  //AddJsonFile:Microsoft.Extensions.Configuration.Json 
                  var Configuration = new ConfigurationBuilder()
                      .SetBasePath(Directory.GetCurrentDirectory())
                      .AddJsonFile("appsettings.json", optional: true)
                      .Build();
                  return Configuration.GetConnectionString("Default");
              }
      
      
              public SqlServerHelper()
              {
                  Console.WriteLine($"{this.GetType().Name}被構造");
              }
      
              //public SqlServerHelper(int i)
              //{
              //    Console.WriteLine($"{this.GetType().Name}被構造");
              //}
      
              public void Query()
              {
                  Console.WriteLine($"{this.GetType().Name}.Query");
              }
          }
      }
      

      我們開始嘗試通過反射創(chuàng)建對象

      //傳統方式創(chuàng)建對象
      IDBHelper dbHelper=new SqlServerHelper();
      

      反射的方式

      1. 動態(tài)讀取DLL
      2. LoadFrom: dll全名稱,需要后綴
      3. LoadFile: 全路徑,需要DLL后綴
      4. Load: dll名稱,不需要后綴
      5. 獲取某一個具體的類型:參數需要是類的全名稱;
      6. 創(chuàng)建對象
      7. 類型轉換
      8. 調用方法
      Assembly assembly =Assembly.LoadFrom("Business.DB.SqlServer.dll");
      //Assembly assembly1=Assembly.LoadFile(@"E:\VS項目\2022年vs項目\ReLearn\ReLearn\bin\Debug\net7.0\Business.DB.SqlServer.dll");
      //Assembly assembly2=Assembly.Load("Business.DB.SqlServer");
      Type type= assembly.GetType("Business.DB.SqlServer.SqlServerHelper");
      object? oInstance= Activator.CreateInstance(type);
      
      //oInstance.Query(); //報錯。因為oInstance當做是一個object類型,object類型是沒有Query方法的;
      //C#語言是一個強類型語言:編譯時你是什么類型,以左邊為準;不能調用是因為編譯器不允許;實際類型一定是SqlServerHelper類型;
      
      //如果使用dynamic 作為類型的聲明,在調用的時候,沒有限制;
      //dynamic:動態(tài)類型;不是編譯時決定類型,避開編譯器的檢查;運行時決定是什么類型
      //dynamic oInstance1= Activator.CreateInstance(type);
      //oInstance1.Query();
      //oInstance1.Get(); //報錯了,因為SqlServerHelper沒有Get方法。
      
      SqlServerHelper  sqlServerHelper = oInstance as SqlServerHelper;
      
      sqlServerHelper.Query();
      

      三、反射實現工廠,斷開依賴

      首先我們先使用傳統的方式創(chuàng)建一個簡單工廠

       public class SimpleFactory
          {
              public static IDBHelper CreateInstance()
              {
                  Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
                  
                  Type type = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");
      
                  object? oInstance = Activator.CreateInstance(type);
                  IDBHelper helper = oInstance as IDBHelper;
                  return helper;
              }
          }
      

      我們在使用的時候,只需要調用CreateInstance返回一個IDBHelper對象即可。
      但是有時候可能會遇到產品經理,讓我們使用不同數據庫去存儲我們的數據的情況,遇到這種情況的時候,可能就需要更改我們的代碼來實現不同數據庫的切換,因此我們就可以通過反射機制,盡可能的達到一勞永逸的結果。
      改造一下我們的簡單工廠模式

       public class SimpleFactory
          {
              public static IDBHelper CreateInstance()
              {
                  string ReflictionConfig = CustomConfigManager.GetConfig("ReflictionConfig");
                  
                  string typeName = ReflictionConfig.Split(',')[0];
                  string dllName = ReflictionConfig.Split(',')[1];
      
               
                  Assembly assembly = Assembly.LoadFrom(dllName);
                  Type type = assembly.GetType(typeName);
      
                  object? oInstance = Activator.CreateInstance(type);
                  IDBHelper helper = oInstance as IDBHelper;
                  return helper;
              }
          }
      
          public static class CustomConfigManager
          {
              public static string GetConfig(string key)
              {
                  var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
                  IConfigurationRoot config = builder.Build();
                  string configValue = config.GetSection(key).Value;
                  return configValue;
              }
          }
      

      創(chuàng)建SqlServerHelper的時候,沒有出現SqlserverHelper;沒有依賴SqlServerHelper;
      依賴的是兩個字符串Business.DB.SqlServer.dll +Business.DB.SqlServer.SqlServerHelper
      去掉對細節(jié)的依賴的;依賴于抽象--不再依賴于細節(jié);----依賴倒置原則; 增強代碼的穩(wěn)定性;

      如果我們要切換到MySql服務器

      1. 按照接口實現一個Mysql幫助類庫
      2. Copy Dll文件到執(zhí)行目錄下
      3. 修改配置文件

      結果:不同功能的靈活切換---程序的配置;
      如果一個新的功能還不存在,只需要把功能實現、dll Copy到執(zhí)行目錄下,修改配置文件---不需要停止程序的運行;
      擴展一個新的功能進來;

      兩者的比較

      1. 傳統方式,必須修改代碼---必須要重新發(fā)布 編譯 發(fā)布到服務器---步驟就很麻煩
      2. 反射實現:斷開了對普通類的依賴;依賴于配置文件+接口(抽象)

      四、反射黑科技--反射可以做到普通方式做不到的事情;反射破壞單例

      先實現一個單例的代碼:

       public sealed class Singleton
          {
              private static Singleton instance;
              private Singleton() { }
      
              static Singleton()
              {
                  instance = new Singleton();
              }
      
              public static Singleton GetInstance() {
                  return instance;
              }
          }
      
      1. 如果私有化修飾--除了反射以外,沒有其他的方法來完成對私有化的訪問的,私有化就只能從內部訪問;
      2. 反射的強大之處---可以做到普通方法做不到的事兒;
      3. 反射動態(tài)記載dll,元數據中只要有的,都可以給找出來;
      4. 完全不用關注權限問題---為所欲為---小暗門。

      創(chuàng)建一個單例以后,我們對比一下創(chuàng)建對象是否是一致的

            Singleton singleton1 = Singleton.GetInstance();
            Singleton singleton2 = Singleton.GetInstance();
            Singleton singleton3 = Singleton.GetInstance();
            Singleton singleton4 = Singleton.GetInstance();
            Console.WriteLine(object.ReferenceEquals(singleton1, singleton2));
            Console.WriteLine(object.ReferenceEquals(singleton2, singleton3));
            Console.WriteLine(object.ReferenceEquals(singleton1, singleton4)
      

      結果為

      下面用反射我們來創(chuàng)建一下我們的對象,

      Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
      Type type = assembly.GetType("Business.DB.SqlServer.Singleton");
      Singleton singleton1 = (Singleton)Activator.CreateInstance(type, true);
      Singleton singleton2 = (Singleton)Activator.CreateInstance(type, true);
      Singleton singleton3 = (Singleton)Activator.CreateInstance(type, true);
      Singleton singleton4 = (Singleton)Activator.CreateInstance(type, true);
      Console.WriteLine(object.ReferenceEquals(singleton1, singleton2));
      Console.WriteLine(object.ReferenceEquals(singleton2, singleton3));
      Console.WriteLine(object.ReferenceEquals(singleton1, singleton4));
      
      

      這樣就達到了通過反射破壞單例的現象。

      五、反射調用方法+反射創(chuàng)建對象的升級篇

      1.反射創(chuàng)建對象

      在通過用反射創(chuàng)建對象的時候,如何調用類的帶參數的構造函數那?下面我們演示一下,如何調用帶參數的構造函數。
      用來反射測試的類

      /// <summary>
          /// 反射測試類
          /// </summary>
          public class ReflectionTest
          {
              #region Identity
              /// <summary>
              /// 無參構造函數
              /// </summary>
              public ReflectionTest()
              {
                  
                  Console.WriteLine($"這里是{this.GetType()}無參數構造函數");
              }
      
              /// <summary>
              /// 帶參數構造函數
              /// </summary>
              /// <param name="name"></param>
              public ReflectionTest(string name)
              {
                  Console.WriteLine($"這里是{this.GetType()} 有參數構造函數");
              }
      
              public ReflectionTest(int id)
              {
                  Console.WriteLine($"這里是{this.GetType()} 有參數構造函數");
              }
      
      
              public ReflectionTest(int id, string name)
              {
      
                  //typeof(int);
      
                  //Type //id.GetType();
      
                  Console.WriteLine($"這里是{this.GetType()} 有參數構造函數");
              }
      
              public ReflectionTest(string name,int id )
              {
      
                  //typeof(int);
      
                  //Type //id.GetType();
      
                  Console.WriteLine($"這里是{this.GetType()} 有參數構造函數");
              }
      
              #endregion
      
              #region Method
              /// <summary>
              /// 無參方法
              /// </summary>
              public void Show1()
              {
                  Console.WriteLine($"這里是{this.GetType()}的Show1" );
              }
              /// <summary>
              /// 有參數方法
              /// </summary>
              /// <param name="id"></param>
              public void Show2(int id)
              {
      
                  Console.WriteLine($"這里是{this.GetType()}的Show2");
              }
              /// <summary>
              /// 重載方法之一
              /// </summary>
              /// <param name="id"></param>
              /// <param name="name"></param>
              public void Show3(int id, string name)
              {
                  Console.WriteLine($"這里是{this.GetType()}的Show3");
              }
              /// <summary>
              /// 重載方法之二
              /// </summary>
              /// <param name="name"></param>
              /// <param name="id"></param>
              public void Show3(string name, int id)
              {
                  Console.WriteLine($"這里是{this.GetType()}的Show3_2");
              }
              /// <summary>
              /// 重載方法之三
              /// </summary>
              /// <param name="id"></param>
              public void Show3(int id)
              {
      
                  Console.WriteLine($"這里是{this.GetType()}的Show3_3");
              }
              /// <summary>
              /// 重載方法之四
              /// </summary>
              /// <param name="name"></param>
              public void Show3(string name)
              {
      
                  Console.WriteLine("這里是{this.GetType()}的Show3_4");
              }
              /// <summary>
              /// 重載方法之五
              /// </summary>
              public void Show3()
              {
      
                  Console.WriteLine($"這里是{this.GetType()}的Show3_1");
              }
              /// <summary>
              /// 私有方法
              /// </summary>
              /// <param name="name"></param>
              private void Show4(string name)  //肯定是可以的
              {
                  Console.WriteLine($"這里是{this.GetType()}的Show4");
              }
              /// <summary>
              /// 靜態(tài)方法
              /// </summary>
              /// <param name="name"></param>
              public static void Show5(string name)
              {
                  Console.WriteLine($"這里是{typeof(ReflectionTest)}的Show5");
              }
              #endregion
          }
      

      反射的代碼

       //Type type = null;
                              //Activator.CreateInstance();//訪問的是無參數構造函數創(chuàng)建對象;
                              //如何訪問帶參數的構造函數呢? 
                              Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
                              Type type = assembly.GetType("Business.DB.SqlServer.ReflectionTest");
                              //a. 調用無參數構造函數的
                              object noParaObject = Activator.CreateInstance(type);
                              //b. 調用有參數的---需要傳遞一個object類型的數組作為參數,參數按照從昨往右匹配;嚴格匹配,按照參數的類型去執(zhí)行對應的和參數類型匹配的構造函數,如果沒有匹配的---報異常
                              object paraObject = Activator.CreateInstance(type, new object[] { 123 });
                              object paraObject1 = Activator.CreateInstance(type, new object[] { "純潔的逗比" });
                              object paraObject2 = Activator.CreateInstance(type, new object[] { 234, "丸印" });
                              object paraObject3 = Activator.CreateInstance(type, new object[] { "Richard", 456 });
      

      2. 反射調用參數方法

      反射調用方法一定要類型轉換后才能調用嗎? ---當然不是的;

      1. 獲取方法MethodInfo
      2. 執(zhí)行MethodInfo 的Invoke方法,傳遞方法所在的類的實例對象+參數

      對于不同的類型的函數
      a. 調用五參數的方法

      Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
      Type type = assembly.GetType("Business.DB.SqlServer.ReflectionTest");
      object oInstance = Activator.CreateInstance(type); 
      MethodInfo show1 = type.GetMethod("Show1");
      show1.Invoke(oInstance, new object[] { });
      show1.Invoke(oInstance, new object[0]);
      show1.Invoke(oInstance, null); 
      

      b. 調用有參數的方法---重載方法--需要通過方法參數類型類區(qū)別方法,傳遞參數--嚴格匹配參數類型

       Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
       Type type = assembly.GetType("Business.DB.SqlServer.ReflectionTest");
       object oInstance = Activator.CreateInstance(type);
       MethodInfo show2 = type.GetMethod("Show2");
       show2.Invoke(oInstance, new object[] { 123 });
      
       MethodInfo show31 = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
       show31.Invoke(oInstance, new object[] { "細雨浮萍", 234 });
      
       MethodInfo show32 = type.GetMethod("Show3", new Type[] { typeof(int) });
       show32.Invoke(oInstance, new object[] { 345 });
      
      
       MethodInfo show33 = type.GetMethod("Show3", new Type[] { typeof(string) });
       show33.Invoke(oInstance, new object[] { "幸福靚裝" });
      
       MethodInfo show34 = type.GetMethod("Show3", new Type[0]);
       show34.Invoke(oInstance, null);
      
      

      c. 調用私有方法,在獲取方法的時候,加上參數BindingFlags.NonPublic | BindingFlags.Instance

      Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
      Type type = assembly.GetType("Business.DB.SqlServer.ReflectionTest");
      object oInstance = Activator.CreateInstance(type);
      MethodInfo show4 = type.GetMethod("Show4", BindingFlags.NonPublic | BindingFlags.Instance);
      show4.Invoke(oInstance, new object[] { "String" });
      

      d. 調用泛型方法: 1. 獲取到方法后,先確定類型,嚴格按照參數類型傳遞參數就可以正常調用
      泛型是延遲聲明,調用的時候,確定類型

      {
          //GenericMethod genericMethod = new GenericMethod();
          //genericMethod.Show<string, int, DateTime>("", 23, DateTime.Now);
      }
      {
          //Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
          //Type type = assembly.GetType("Business.DB.SqlServer.GenericMethod");
          //object oInstance = Activator.CreateInstance(type);
          //MethodInfo show = type.GetMethod("Show");
          ////在執(zhí)行之前選喲確定是什么類型; 
          //MethodInfo genericshow = show.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(Dat
          //genericshow.Invoke(oInstance, new object[] { 123, "暖風昔人", DateTime.Now });
          //genericshow.Invoke(oInstance, new object[] { "暖風昔人", 123, DateTime.Now });
      
          ////show.Invoke(); //到到底給什么類型呢? 泛型,其實不確定的類型的;
      }
      {
      
          //Console.WriteLine(typeof(GenericClass<,,>)); 
          //Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
          //Type type = assembly.GetType("Business.DB.SqlServer.GenericClass`3");
          //Type generType = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
          //object oInstance = Activator.CreateInstance(generType); 
          //MethodInfo show = generType.GetMethod("Show");
          //show.Invoke(oInstance,new object[] { 123, "赤", DateTime.Now });
      }
      {
          //Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
          //Type type = assembly.GetType("Business.DB.SqlServer.GenericDouble`1");
          //Type generType = type.MakeGenericType(new Type[] { typeof(int) });
          //object oInstance = Activator.CreateInstance(generType);
          //MethodInfo show = generType.GetMethod("Show");
      
          //MethodInfo genericMethod = show.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) }); 
          //genericMethod.Invoke(oInstance, new object[] { 123, "魚兒", DateTime.Now });
      }
      
      

      六、反射多種應用場景

      1.反射+ 配置文件+ 工廠-----后面要講的IOC容器---IOC容器的雛形;簡單版本的IOC容器;
      2.調用方法--需要類型名稱+ 方法名稱就可以調用到方法 ---類類名稱(字符串)+ 方法名稱(字符串) ===就可以去調用方法--MVC框架
      創(chuàng)建一個MVC ---http://localhost:64527/Home/Index 就可以調用到Index方法---就選需要創(chuàng)建Home的實例;執(zhí)行Index方法---當然是反射啊;

      七、 反射的局限性

      1. 有局限----性能問題
      2. 測試用例:普通方式循環(huán)100000次創(chuàng)建對象+方法調用:17 ms
        反射方式循環(huán)100000此創(chuàng)建對象+方法調用:4544ms
        代碼
       public class Monitor
          {
              public static void Show()
              {
                  Console.WriteLine("*******************Monitor*******************");
                  long commonTime = 0;
                  long reflectionTime = 0;
                  {
                      Stopwatch watch = new Stopwatch();
                      watch.Start();
                      for (int i = 0; i < 1000_000; i++) //1000000000
                      {
                          IDBHelper iDBHelper = new SqlServerHelper();
                          iDBHelper.Query();
                      }
                      watch.Stop();
                      commonTime = watch.ElapsedMilliseconds;
                  }
                  {
                      Stopwatch watch = new Stopwatch();
                      watch.Start();
                      //Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");//1 動態(tài)加載
                      //Type dbHelperType = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");//2 獲取類型  
                      for (int i = 0; i < 1000_000; i++)
                      {
                          Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");//1 動態(tài)加載
                          Type dbHelperType = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");//2 獲取類型  
                          object oDBHelper = Activator.CreateInstance(dbHelperType);//3 創(chuàng)建對象
                          IDBHelper dbHelper = (IDBHelper)oDBHelper;//4 接口強制轉換
                          dbHelper.Query();//5 方法調用
                      }
                      watch.Stop();
                      reflectionTime = watch.ElapsedMilliseconds;
                  }
      
                  Console.WriteLine($"commonTime={commonTime} reflectionTime={reflectionTime}");
              }
          }
      

      運行的結果為:

      1. 第二次運行: 普通方式:15ms 反射方式:4517ms
        確實有性能問題,主要損耗性能是加載DLL的時候損耗的,
        怎么優(yōu)化一下?
        把動態(tài)加載Dll部分緩存起來了;每次直接使用加載的dll;
      Stopwatch watch = new Stopwatch();
      watch.Start();
      Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");//1 動態(tài)加載
      Type dbHelperType = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");//2 獲取類型
      for (int i = 0; i < 1000_000; i++)
      {
      
          object oDBHelper = Activator.CreateInstance(dbHelperType);//3 創(chuàng)建對象
          IDBHelper dbHelper = (IDBHelper)oDBHelper;//4 接口強制轉換
          dbHelper.Query();//5 方法調用
      }
      watch.Stop();
      reflectionTime = watch.ElapsedMilliseconds;
      
      

      使用反射的建議:

      1. 反射確實有性能問題
      2. 需要理性對待,就不用嗎?當然要用;因為反射的經過優(yōu)化之后其實性能差也沒有差多少的;因為反射能量確實是太大了,大家以后在工作中,可以放心使用;

      八、反射調用字段

      一個類的內部,除了構造函數、方法、屬性、字段。

       public class People
          {
              public People()
              {
                  Console.WriteLine("{0}被創(chuàng)建", this.GetType().FullName);
              } 
              public int Id { get ; set; } //帶有Get  Set 方法的叫做屬性
               
              public string Name { get; set; }
      
              public int Age { get; set; }
      
              public int Sex { get; set; }
      
              public string Description;  //字段           
          }
      

      傳統方式使用屬性和字段

       //傳統方式使用屬性和字段
                          {
                              Console.WriteLine("***********賦值*************");
                              People people = new People();
                              people.Id = 134;
                              people.Name = "陳大寶";
                              people.Age = 25;
                              people.Description = "高級班的VIP學員";
                              people.Sex = 1;
                              People people1 = new People()
                              {
                                  Id = 134,
                                  Name = "陳大寶",
                                  Age = 25,
                                  Description = "高級班的VIP學員"
                              };
                              Console.WriteLine("***********取值*************");
                              Console.WriteLine($"people.Id={people.Id}");
                              Console.WriteLine($"people.Name={people.Name}");
                              Console.WriteLine($"people.Age={people.Age}");
                              Console.WriteLine($"people.Sex={people.Sex}");
                              Console.WriteLine($"people.Description={people.Description}");
                          }
      

      反射方式

      Console.WriteLine("***********反射方式*************");
                          {
                              Type type = typeof(People);
                              object pObject = Activator.CreateInstance(type);
                              //pObject.Id=234; 
                              foreach (var prop in type.GetProperties())
                              {
                                  //Console.WriteLine(prop.Name);
                                  //逐個屬性賦值
                                  if (prop.Name.Equals("Id"))
                                  {
                                      prop.SetValue(pObject, 134);
                                  }
                                  else if (prop.Name.Equals("Name"))
                                  {
                                      prop.SetValue(pObject, "陳大寶");
                                  }
                                  else if (prop.Name.Equals("Age"))
                                  {
                                      prop.SetValue(pObject, 25);
                                  }
                                  //else if (prop.Name.Equals("Age"))
                                  //{
                                  //    prop.SetValue(pObject, 25);
                                  //}
                              }                      
                              foreach (var prop in type.GetProperties())
                              {
                                  Console.WriteLine($"people.{prop.Name}={prop.GetValue(pObject)}");
      
                                  //if (prop.Name.Equals("Id"))
                                  //{
                                  //    prop.GetValue(pObject);
                                  //}
                                  //else if (prop.Name.Equals("Name"))
                                  //{
                                  //    prop.GetValue(pObject);
                                  //}
                                  //else if (prop.Name.Equals("Age"))
                                  //{
                                  //    prop.GetValue(pObject);
                                  //   }
                              }
                          }
      

      總結:

      1. 普通方法調用屬性字段---簡單快捷
      2. 反射操作---稍微麻煩點
      3. 讓我們的程序更加穩(wěn)定---
      4. 如果說People增加一個字段呢?增加一個屬性呢?--普通方法就必須要修改代碼---重新編譯發(fā)布----不穩(wěn)定
      5. 反射設置值:好像沒啥優(yōu)勢
      6. 反射取值:不需要修改代碼---代碼就更加穩(wěn)定

      九、反射+ADO.NET時間數據庫訪問層---手寫ORM框架

      1. ORM--對象關系映射
      2. 可以通過依賴于某個實體對象--做到對數據庫中數據的操作
       public class SqlServerHelper : IDBHelper
          {
      
              //Nuget:System.Data.SqlClient
      
              private string ConnectionString = "Data Source=10.10.33.251; Database=ZhaoXiPracticeDB; User ID=sa; Password=7ujm&UJM; MultipleActiveResultSets=True";
      
              private static string GetConnection()
              {
                  //Nuget引入:
                  //SetBasePath:Microsoft.Extensions.Configuration.FileExtensions
                  //AddJsonFile:Microsoft.Extensions.Configuration.Json 
                  var Configuration = new ConfigurationBuilder()
                   .SetBasePath(Directory.GetCurrentDirectory())
                   .AddJsonFile("appsettings.json", optional: true)
                   .Build();
                  return Configuration.GetConnectionString("Default");
              }
      
      
              public SqlServerHelper()
              {
                  //Console.WriteLine($"{this.GetType().Name}被構造");
              }
      
              //public SqlServerHelper(int i)
              //{
              //    Console.WriteLine($"{this.GetType().Name}被構造");
              //}
      
              public void Query()
              {
                  //Console.WriteLine($"{this.GetType().Name}.Query");
              }
      
              /// <summary>
              /// 查詢Company
              /// 條件:
              /// 1.必須有一個Id字段--繼承BaseModel
              /// 2.要求實體對象中的屬性結構必須和數據完全一致
              /// </summary>
              public SysCompany QuerySysCompany(int id)
              {
                  //開始ORM
                  //1.鏈接數據---數據庫鏈接字符串ConnectionString 
                  //2.準備SqlConnection,使用數據庫鏈接字符串
      
                  //SysCompany result = new SysCompany();
                  //7.反射創(chuàng)建對象oReulst--- 給oReulst 賦值然后返回  oReulst
                  Type type = typeof(SysCompany);
                  object oReulst = Activator.CreateInstance(type);
      
                  using (SqlConnection connection = new SqlConnection(ConnectionString))
                  {
                      connection.Open();//打開數據庫鏈接
                      //3.準時Sql語句
                      #region MyRegion
                      string sql = @"SELECT [Id]
                                        ,[Name]
                                        ,[CreateTime]
                                        ,[CreatorId]
                                        ,[LastModifierId]
                                        ,[LastModifyTime]
                                          FROM [ZhaoXiPracticeDB].[dbo].[SysCompany] where  id=" + id;
                      #endregion 
                      //4.準備SqlCommand
                      SqlCommand sqlCommand = new SqlCommand(sql, connection);
                      //5.通過SqlCommand對象執(zhí)行Sql語句
                      SqlDataReader reader = sqlCommand.ExecuteReader();
                      //6.開始獲取數據
      
                      if (reader.Read())
                      {
                          //object oId = reader["Id"];
                          //result.Id = Convert.ToInt32(oId);//不行;
                          //object oName = reader["Name"]; 
                          //8.反射賦值?
                          foreach (var prop in type.GetProperties())
                          {
                              //if (prop.Name.Equals("Id"))
                              //{
                              //    prop.SetValue(oReulst, reader["Id"]); //Id
                              //}
                              //else if (prop.Name.Equals("Name"))
                              //{
                              //    prop.SetValue(oReulst, reader[prop.Name]);
                              //}
                              //else if (prop.Name.Equals("CreateTime"))
                              //{
                              //    prop.SetValue(oReulst, reader[prop.Name);
                              //}
      
                              //else if (true)
                              //{
                              //.......
                              //}
      
                              Console.WriteLine(prop.GetValue(oReulst, null));
                             // Console.WriteLine(prop.Name);
                             
                        
      
                          }
                      }
                      //問題來了,數據可以查詢到---需要返回一個對象--需要賦值給對象,然后返回對象;----反射 
                  }
                  return (SysCompany)oReulst;
              }
      }
      

      十、Emit技術:在運行時去動態(tài)的生成Dll、Exe包括dll內部的方法、屬性、字段

      1. 動態(tài)--;可以在代碼運行的時候去動態(tài)的定義業(yè)務邏輯;
      2. 偏向于底層--學習成本比較高 除非是非常復雜的業(yè)務邏輯,一般情況,用的比較少---動態(tài)代理的時候,還會再講的;
        ReflectionEmit.cs
      public class ReflectionEmit
          {
              public static void Show()
              {
      
                  // AssemblyBuilder// 建造者模式---創(chuàng)建Assembly
      
                  //AssemblyName assemblyName = new AssemblyName("DynamicAssemblyExample");
      
                  AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynamicAssemblyExample"), AssemblyBuilderAccess.RunAndCollect);
      
                  // 對于單個模塊程序集,模塊名稱通常為;程序集名稱加上擴展名。  
                  ModuleBuilder modulebuilder = assemblyBuilder.DefineDynamicModule("MyModal"); //托管模塊
                  TypeBuilder typebuilder = modulebuilder.DefineType("MyDynamicType", TypeAttributes.Public);
      
                  //Type type= typebuilder.CreateType();
      
                  // 在Type中生成私有字段
                  FieldBuilder fieldBuilder = typebuilder.DefineField("NumberField", typeof(int), FieldAttributes.Public);
      
                  // 定義一個接受整數參數的構造函數,儲存在私人區(qū)域。  
                  Type[] parameterTypes = { typeof(int) };
                  ConstructorBuilder ctor1 = typebuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, parameterTypes);
      
                  //中間語言的生成者
                  ILGenerator ctor1IL = ctor1.GetILGenerator();
      
                  //對于構造函數,參數0是對新 
                  //實例。在調用base之前將其推到堆棧上 
                  //類構造函數。指定的默認構造函數 
                  //通過傳遞 
                  //類型(Type.EmptyTypes)到GetConstructor。 
      
                  ctor1IL.Emit(OpCodes.Ldarg_0);
                  ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
      
                  //在推送參數之前,先將實例推送到堆棧上 
                  //將被分配給私有字段m\u編號。 
                  ctor1IL.Emit(OpCodes.Ldarg_0);
                  ctor1IL.Emit(OpCodes.Ldarg_1);
                  ctor1IL.Emit(OpCodes.Stfld, fieldBuilder);
                  ctor1IL.Emit(OpCodes.Ret);
      
                  //完成構造函數傳值, Int 設置給字段--測試代碼
                  {
                      //MyDynamicType myDynamicType = new MyDynamicType(123456);
                      //int number = myDynamicType.NumberField;
      
                      //// 動態(tài)的生成程序集;
                      //// 動態(tài)的生成類;
                      //// 動態(tài)的生成字段;
                      //// 動態(tài)的生成構造函數;
                      //Type type1 = typebuilder.CreateType();
                      //object oInstacne = Activator.CreateInstance(type1, new object[] { 123456 });
                      //FieldInfo fieldInfo = type1.GetField("NumberField");
                      //object numberFieldResult = fieldInfo.GetValue(oInstacne);
                  }
      
                  MethodBuilder consoleMethod = typebuilder.DefineMethod("ConsoleMethod", MethodAttributes.Public | MethodAttributes.Static, null, null);
      
                  ILGenerator consoleMethodIL = consoleMethod.GetILGenerator();
                  consoleMethodIL.Emit(OpCodes.Ldstr, "歡迎來到高級班第15期進階學習");
                  consoleMethodIL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
                  consoleMethodIL.Emit(OpCodes.Ret); //寫IL最后一定要Ret
      
      
      
                  {
                      Console.WriteLine("測試。。。。。。");
                      Type type1 = typebuilder.CreateType();
                      object oInstacne = Activator.CreateInstance(type1, new object[] { 123456 });
                      MethodInfo myMethod = type1.GetMethod("ConsoleMethod");
                      object oResult = myMethod.Invoke(oInstacne, null);
      
                  } 
                  MethodBuilder AddMethod = typebuilder.DefineMethod("AddMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(int), typeof(int) });
                  ILGenerator AddMethodIL = AddMethod.GetILGenerator();
                  AddMethodIL.Emit(OpCodes.Ldarg_0);
                  AddMethodIL.Emit(OpCodes.Ldarg_1);
                  AddMethodIL.Emit(OpCodes.Add_Ovf_Un);
                  AddMethodIL.Emit(OpCodes.Ret);
                  {
                      //Console.WriteLine("測試。。。。。。");
                      //Type type1 = typebuilder.CreateType();
                      //object oInstacne = Activator.CreateInstance(type1, new object[] { 123456 });
                      //MethodInfo myMethod = type1.GetMethod("AddMethod");
                      //object oResult = myMethod.Invoke(oInstacne, new object[] { 12, 34 }); 
                  }
              }
          }
      

      main.cs

      Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
                          Module[] modules = assembly.GetModules();
                          foreach (var module in modules)
                          {
                              Console.WriteLine(module.Name);
                              foreach (var type in module.GetTypes())
                              {
                                  Console.WriteLine(type.Name);
                              }
                          }
                          ReflectionEmit.Show();
      
      
      posted @ 2023-04-05 18:02  飄雨的河  閱讀(69)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩有码中文字幕国产| 亚欧美日韩香蕉在线播放视频| 欧洲免费一区二区三区视频| 一本一道av无码中文字幕﹣百度 | 色成人亚洲| 亚洲av日韩av中文高清性色| 最新的国产成人精品2020| 国产精品成人中文字幕 | 国产精品国产三级国产av剧情| 国产精品免费久久久免费| 老鸭窝在线视频| 亚洲色av天天天天天天| 国内极度色诱视频网站| 农村老熟妇乱子伦视频| 亚洲AV成人无码久久精品| 久久精产国品一二三产品| 色九九视频| 国产又爽又黄的精品视频| 欧美成人精品手机在线| 亚洲国产午夜精品福利| 丰满无码人妻热妇无码区| 久久精品无码鲁网中文电影| 一本久道久久综合中文字幕| 蜜臀av黑人亚洲精品| 亚洲国产欧美日韩另类| 国产中文字幕一区二区| 最新国产精品亚洲| 欧美激烈精交gif动态图| 中文字幕午夜福利片午夜福利片97| 久久中文字幕日韩无码视频| 国产盗摄xxxx视频xxxx | 蜜臀av一区二区三区日韩| 亚洲欧洲日产国码无码久久99| 精品视频福利| 亚洲精品无码久久千人斩| 国产无套精品一区二区| 夜夜影院未满十八勿进| 91中文字幕在线一区| 精品久久久久中文字幕日本| 免费看亚洲一区二区三区| 最新国产AV最新国产在钱|