一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C# - C# 反射與dynamic最佳組合示例代碼

C# 反射與dynamic最佳組合示例代碼

2022-01-21 13:48DW039 C#

這篇文章主要介紹了C# 反射與dynamic最佳組合示例代碼,需要的朋友可以參考下

在 c# 中反射技術應用廣泛,至于什么是反射.........你如果不了解的話,請看下段說明,否則請跳過下段。廣告一下:喜歡我文章的朋友請關注一下我的blog,這也有助于提高本人寫作的動力。

反射:當你背對一個美女或帥哥卻不能回頭仔細觀察研究時(純屬虛構,如有巧合、純屬雷同),一面小鏡子就能滿足你的需求。在 c# 編程過程中也經常遇到類似的情況:有一個別人寫的 dll 類庫你想使用卻沒程序文檔資料......此時通過 c# runtime 提供的功能,你可以把該 dll 類庫加載到你的程序中,并細細研究 dll 的每一部分內容,這就是 c# 中的反射。

個人認為反射最突出的優點或存在的合理性:在不修改程序原碼的情況下,實現程序功能的動態調整(runtime動態對象創建)

示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
interface irun {
 void run();
}
class person : irun
{
 public void run()
 {
  console.writeline("走,去lol啊!");
 }
}
class car : irun
{
 public void run()
 {
  console.writeline("嗚...........");
 }
}
class program
{
 static void main(string[] args)
 {
  irun e = new person();
  e.run();
  console.readline();
 }
}

如果將上面的run功能并不一定是由person來執行,有時需要是car有時需要person。常見的解決方案是添加 if 等判斷結構,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void main(string[] args)
 {
  console.writeline("請輸入:car或person");
  string type = console.readline();
  irun e = null;
  if ("car" == type)
  {
   e = new car();
  }else if("person" == type)
  {
   e = new person();
  }
  if(null != e)
   e.run();
  console.readline();
 }

這種結構確是解決了現在的需求,但并不健壯。隨著 irun 接口實現、相關類的繼承的增加,上面的判斷結構也會飛速增長。面向對象編程、設計模式均遵循的一大原則就是封裝變換,所以上面的程序無法很好的應對變化。在此我們并不涉及 “設計模式的” 的知識,因此下面的示例代碼只為簡化上面的程序、并未刻意套用設計模式相關知識。如下:     

?
1
2
3
4
5
6
7
8
9
10
11
static void main(string[] args)
 {
  console.writeline("請輸入:car或person");
  string type = console.readline();
  string classpath = string.format("namespace.{0}", type);
  irun e = activator.createinstance(null, classpath).unwrap() as irun;
 
  if(null != e)
   e.run();
  console.readline();
 }

經過上面的修改,程序可自行根據用戶的輸入,通過activator.createinstance創建 irun 的實例,程序此處不會再隨 irun 的實現者增多這種問題的影響而發生變化。上面的這種優點就是通過反射得到的,也是我所認為的“反射存在的合理性”。

activator、assembly 實現反射方式創建對象

c#中反射方式創建對象可以通過 activator.createinstance(靜態)和 assembly.createinstance(非靜態)來實現,其中assembly.createinstance 內部調用的仍是activator.createinstance。

根據要動態創建的類型對象是否處于當前程序集之中,可將反射創建對象分為:創建程序集內的類型對象與創建程序集外的類型對象。

創建程序集內的類型對象

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void reflectionirun1(string classname)
{
 string classpath = string.format("namespace.{0}", classname);
 //參數 null ,指出所要創建類型對象位于當前程序集
 var handler = activator.createinstance(null, classpath);
 irun e = (irun)handler.unwrap();
 console.writeline(e.run());
}
private static void reflectionirun2(string classname)
{
 string classpath = string.format("namespace.{0}", classname);
 //typeof(irun).assembly 獲取 irun 類型所在的程序集
 object obj = typeof(irun).assembly.createinstance(null, classpath);
 irun e = (irun)obj;
 console.writeline(e.run());
}

創建程序集外的類型對象

項目中增加一個 類庫 (另一個程序集),如下圖:

C# 反射與dynamic最佳組合示例代碼

添加一個 boss 類,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace lib
{
 public class boss
 {
  private string name = "老大";
  
  public string name{
   get {return name;}
  }
  public string talk()
  {
   return "你們都被開除了......";
  }
  //老板不會算賬,總是多付錢,所以很有自知之明的將payfor設為private,防止外部人員調用
  private int payfor(int total)
  {
   return total + 10;
  }
 }
}

獲取 一個 boss 對象前,首先添加對 lib 的引用,獲取示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void reflectionboss1()
 {
  string classpath ="lib.boss";
  //"lib" 參數指明要加載的程序集(即要創建的對象類型在哪個程序集中定義)
  var handler = activator.createinstance("lib", classpath);
  boss b = handler.unwrap() as boss;
  console.writeline(b.talk());
 }
 private static void reflectionboss2()
 {
  string classpath ="lib.boss";
  //assembly.load("lib") 加載的程序集(即要創建的對象類型在哪個程序集中定義)
  var assembly = assembly.load("lib");
  boss b = (boss)assembly.createinstance(classpath);
  console.writeline(b.talk());
 }

關于反射時clr如何查找并定位要加載的程序集,請參考msdn中關于反射相關的知識。

反射訪問字段、調用方法(屬性)

反射除可以幫我們動態創建對象外,還可幫我們動態訪問對象的方法(屬性)或字段,因 c# 版本不同具體方法會有變更或擴展,更深入內容請參考msdn。下面僅作簡單示例(標準用法)。

給老板改名,示例:      

?
1
2
3
4
5
6
7
8
9
10
11
private static void reflectionboss1()
 {
  string classpath = "lib.boss";
  //"lib" 參數指明要加載的程序集(即要創建的對象類型在哪個程序集中定義)
  var handler = activator.createinstance("lib", classpath);
  boss b = handler.unwrap() as boss;
  //關鍵代碼
  fieldinfo f = b.gettype().getfield("name", bindingflags.getfield | bindingflags.nonpublic | bindingflags.instance);
  f.setvalue(b, "小二");
  console.writeline("{0}:{1}", b.name, b.talk());
 }

輸出:

C# 反射與dynamic最佳組合示例代碼

讓老板付錢:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static void reflectionboss1()
  {
   string classpath = "lib.boss";
   //"lib" 參數指明要加載的程序集(即要創建的對象類型在哪個程序集中定義)
   var handler = activator.createinstance("lib", classpath);
   boss b = handler.unwrap() as boss;
   //關鍵代碼
   methodinfo method = b.gettype().getmethod("payfor", bindingflags.invokemethod | bindingflags.nonpublic | bindingflags.instance);
   object money = method.invoke(b, new object[] { 10 });
   console.writeline("dw039:老大給我報銷10元錢車費......");
   console.writeline("{0}:.....,算不清了,給你這些吧。",b.name);
   console.writeline("dw039:......");
   console.writeline("{0}:{1}", b.name,money);
   console.writeline("dw039:老大你真棒!");
  }

輸出:

C# 反射與dynamic最佳組合示例代碼

dynamic 與 反射 雙劍合璧

因為反射是運行時的類型操作,所以在編程時面臨類型不確定的問題。根據上一篇《c# 匿名對象(匿名類型)、var、動態類型 dynamic》講得 dynamic 動態類型結合我們編寫的反射程序,可以大大優化程序邏輯(訪問受保護級別限制的代碼不在此范圍內)。

上面代碼的優化:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static void reflectionboss1()
  {
   string classpath ="lib.boss";
   var handler = activator.createinstance("lib", classpath);
   dynamic b = handler.unwrap();
   console.writeline(b.talk());
  }
  private static void reflectionboss2()
  {
   string classpath ="lib.boss";
   var assembly = assembly.load("lib");
   dynamic b = assembly.createinstance(classpath);
   console.writeline(b.talk());
  }

通過 dynamic 動態類型對象 b 來調用反射得到對象的屬性、方法可直接調用,從而省去了頻繁的類型轉換操作。

反射常見應用場景

應用場景我印象最深刻的是 ms petshop 示例,從sql server 數據庫切換到 oracle 數據庫時反射獲得不同的數據訪問層。然我實際項目中從未遇到過中途切換數據庫的情況,其他應用場景基本類似上面的示例。如果朋友你發現更多的應用場景,請給予補充,3ks。

反射的優缺點

優點:反射使程序更靈活

缺點:反射運行速度相對較慢

至于反射相比普通程序慢,我沒有進行過測試也不打算進行。現實情況是:ms提倡使用 dynamic、mvc流行、ms對clr不斷優化、機器性能的提升,所以你在開發中無需過多考慮反射的性能問題。如果你寫的程序運行速度出現了瓶頸(應首先確保自己程序寫的合理),研究一下數據庫優化、數據緩存、web緩存、負載均衡等技術我認為更實際一些。

原文鏈接:http://www.cnblogs.com/dw039/p/7476011.html

延伸 · 閱讀

精彩推薦
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    這篇文章主要介紹了C# 實現對PPT文檔加密、解密及重置密碼的操作方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    E-iceblue5012022-02-12
  • C#Unity3D實現虛擬按鈕控制人物移動效果

    Unity3D實現虛擬按鈕控制人物移動效果

    這篇文章主要為大家詳細介紹了Unity3D實現虛擬按鈕控制人物移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一...

    shenqingyu060520232410972022-03-11
  • C#深入解析C#中的交錯數組與隱式類型的數組

    深入解析C#中的交錯數組與隱式類型的數組

    這篇文章主要介紹了深入解析C#中的交錯數組與隱式類型的數組,隱式類型的數組通常與匿名類型以及對象初始值設定項和集合初始值設定項一起使用,需要的...

    C#教程網6172021-11-09
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

    這篇文章主要為大家詳細介紹了C#實現XML文件讀取的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Just_for_Myself6702022-02-22
  • C#WPF 自定義雷達圖開發實例教程

    WPF 自定義雷達圖開發實例教程

    這篇文章主要介紹了WPF 自定義雷達圖開發實例教程,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下...

    WinterFish13112021-12-06
  • C#C#通過KD樹進行距離最近點的查找

    C#通過KD樹進行距離最近點的查找

    這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的查找,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    帆帆帆6112022-01-22
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    這篇文章主要介紹了C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題,簡單描述了訪問者模式的定義并結合具體實例形式分析了C#使用訪問者模式解決長...

    GhostRider9502022-01-21
  • C#C#裁剪,縮放,清晰度,水印處理操作示例

    C#裁剪,縮放,清晰度,水印處理操作示例

    這篇文章主要為大家詳細介紹了C#裁剪,縮放,清晰度,水印處理操作示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    吳 劍8332021-12-08
主站蜘蛛池模板: 好舒服好爽再快点视频 | 九九99靖品 | 好姑娘在线完整版视频 | 日本免费一区二区三区四区五六区 | 国产免费成人在线视频 | 91精品大神国产在线播放 | 桃乃木香在线 | 亚洲AV蜜桃永久无码精品无码网 | 色人阁小说| 国亚洲欧美日韩精品 | 亚洲AV福利天堂一区二区三 | 秋霞黄色网| 国产欧美一区二区精品久久久 | 视频在线观看国产 | 国产国拍亚洲精品av | 免费在线观看日本 | 美女任你模 | 四虎影院永久网址 | 美女脱了内裤让男生玩屁股 | 日本一区二区在线不卡 | 国产精品久久国产精品99 | 乳 好大h | 日韩在线免费 | 久久综合给会久久狠狠狠 | 色老头综合网 | 午夜熟女插插XX免费视频 | 四虎网站 | 波多野结衣之高校教师 | 男女被爆动漫羞羞动漫 | 国产乱子伦在线观看不卡 | youjizzxxx69日本 | 石原莉奈adn093店长未婚妻 | 欧美一级在线全免费 | 亚洲AV久久久噜噜噜久久 | 亚洲精品www久久久久久久软件 | 午夜视频一区二区三区 | 精品日本三级在线观看视频 | 婷婷丁香色综合狠狠色 | 黄动漫车车好快的车车a | 亚洲123区| 黑人粗长大战亚洲女 |