<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C# 反射、與dynamic最佳組合

          共 6710字,需瀏覽 14分鐘

           ·

          2022-01-16 05:29

          在 C# 中反射技術(shù)應(yīng)用廣泛,至于什么是反射.........你如果不了解的話,請(qǐng)看下段說(shuō)明,否則請(qǐng)?zhí)^(guò)下段。廣告一下:喜歡我文章的朋友請(qǐng)關(guān)注一下我的blog,這也有助于提高本人寫作的動(dòng)力。

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

          個(gè)人認(rèn)為反射最突出的優(yōu)點(diǎn)或存在的合理性:在不修改程序原碼的情況下,實(shí)現(xiàn)程序功能的動(dòng)態(tài)調(diào)整(Runtime動(dòng)態(tài)對(duì)象創(chuàng)建

          示例:


          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來(lái)執(zhí)行,有時(shí)需要是Car有時(shí)需要Person。常見(jiàn)的解決方案是添加 if 等判斷結(jié)構(gòu),如下:


          static void Main(string[] args) { Console.WriteLine("請(qǐng)輸入: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(); }


          這種結(jié)構(gòu)確是解決了現(xiàn)在的需求,但并不健壯。隨著 IRun 接口實(shí)現(xiàn)、相關(guān)類的繼承的增加,上面的判斷結(jié)構(gòu)也會(huì)飛速增長(zhǎng)。面向?qū)ο缶幊獭⒃O(shè)計(jì)模式均遵循的一大原則就是封裝變換,所以上面的程序無(wú)法很好的應(yīng)對(duì)變化。在此我們并不涉及 “設(shè)計(jì)模式的” 的知識(shí),因此下面的示例代碼只為簡(jiǎn)化上面的程序、并未刻意套用設(shè)計(jì)模式相關(guān)知識(shí)。如下:


          static void Main(string[] args) { Console.WriteLine("請(qǐng)輸入: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(); }


          經(jīng)過(guò)上面的修改,程序可自行根據(jù)用戶的輸入,通過(guò)Activator.CreateInstance創(chuàng)建 IRun 的實(shí)例,程序此處不會(huì)再隨 IRun 的實(shí)現(xiàn)者增多這種問(wèn)題的影響而發(fā)生變化。上面的這種優(yōu)點(diǎn)就是通過(guò)反射得到的,也是我所認(rèn)為的“反射存在的合理性”。

          Activator、Assembly?實(shí)現(xiàn)反射方式創(chuàng)建對(duì)象

          C#中反射方式創(chuàng)建對(duì)象可以通過(guò) Activator.CreateInstance(靜態(tài))和 Assembly.CreateInstance(非靜態(tài))來(lái)實(shí)現(xiàn),其中Assembly.CreateInstance 內(nèi)部調(diào)用的仍是Activator.CreateInstance。

          根據(jù)要?jiǎng)討B(tài)創(chuàng)建的類型對(duì)象是否處于當(dāng)前程序集之中,可將反射創(chuàng)建對(duì)象分為:創(chuàng)建程序集內(nèi)的類型對(duì)象與創(chuàng)建程序集外的類型對(duì)象。

          創(chuàng)建程序集內(nèi)的類型對(duì)象

          8cd0561c3591db70a157763b2c4f161c.webp


          private static void ReflectionIRun1(string className) { string classPath = String.Format("namespace.{0}", className); //參數(shù) null ,指出所要?jiǎng)?chuàng)建類型對(duì)象位于當(dāng)前程序集 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()); }


          創(chuàng)建程序集外的類型對(duì)象

          項(xiàng)目中增加一個(gè) 類庫(kù) (另一個(gè)程序集),如下圖:

          389be4b1e4b71965f308045cfd1f568b.webp

          添加一個(gè) Boss 類,如下:


          namespace Lib{ public class Boss { private string name = "老大"; public string Name{ get {return name;} } public string Talk() { return "你們都被開(kāi)除了......"; } //老板不會(huì)算賬,總是多付錢,所以很有自知之明的將Payfor設(shè)為private,防止外部人員調(diào)用 private int Payfor(int total) { return total + 10; } }}


          獲取 一個(gè) Boss 對(duì)象前,首先添加對(duì) Lib 的引用,獲取示例如下:


          private static void ReflectionBoss1() { string classPath ="Lib.Boss"; //"Lib" 參數(shù)指明要加載的程序集(即要?jiǎng)?chuàng)建的對(duì)象類型在哪個(gè)程序集中定義) 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") 加載的程序集(即要?jiǎng)?chuàng)建的對(duì)象類型在哪個(gè)程序集中定義) var assembly = Assembly.Load("Lib"); Boss b = (Boss)assembly.CreateInstance(classPath); Console.WriteLine(b.Talk()); }


          關(guān)于反射時(shí)CLR如何查找并定位要加載的程序集,請(qǐng)參考MSDN中關(guān)于反射相關(guān)的知識(shí)。

          反射訪問(wèn)字段、調(diào)用方法(屬性

          反射除可以幫我們動(dòng)態(tài)創(chuàng)建對(duì)象外,還可幫我們動(dòng)態(tài)訪問(wèn)對(duì)象的方法(屬性)或字段,因 C# 版本不同具體方法會(huì)有變更或擴(kuò)展,更深入內(nèi)容請(qǐng)參考MSDN。下面僅作簡(jiǎn)單示例(標(biāo)準(zhǔn)用法)。

          給老板改名,示例:?


          private static void ReflectionBoss1() { string classPath = "Lib.Boss"; //"Lib" 參數(shù)指明要加載的程序集(即要?jiǎng)?chuàng)建的對(duì)象類型在哪個(gè)程序集中定義) var handler = Activator.CreateInstance("Lib", classPath); Boss b = handler.Unwrap() as Boss; //關(guān)鍵代碼 FieldInfo f = b.GetType().GetField("name", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance); f.SetValue(b, "小二");
          Console.WriteLine("{0}:{1}", b.Name, b.Talk()); }


          輸出:

          702016c1eefe937fcb5765f3c7d181dc.webp

          讓老板付錢:


          private static void ReflectionBoss1() { string classPath = "Lib.Boss"; //"Lib" 參數(shù)指明要加載的程序集(即要?jiǎng)?chuàng)建的對(duì)象類型在哪個(gè)程序集中定義) var handler = Activator.CreateInstance("Lib", classPath); Boss b = handler.Unwrap() as Boss; //關(guān)鍵代碼 MethodInfo method = b.GetType().GetMethod("Payfor", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance); object money = method.Invoke(b, new object[] { 10 });
          Console.WriteLine("DW039:老大給我報(bào)銷10元錢車費(fèi)......"); Console.WriteLine("{0}:.....,算不清了,給你這些吧。",b.Name); Console.WriteLine("DW039:......"); Console.WriteLine("{0}:{1}", b.Name,money); Console.WriteLine("DW039:老大你真棒!"); }


          輸出:

          b7656d951e0147d215b1e364a944110e.webp

          dynamic 與 反射 雙劍合璧

          因?yàn)榉瓷涫沁\(yùn)行時(shí)的類型操作,所以在編程時(shí)面臨類型不確定的問(wèn)題。根據(jù)上一篇《C# 匿名對(duì)象(匿名類型)、var、動(dòng)態(tài)類型 dynamic》講得 dynamic 動(dòng)態(tài)類型結(jié)合我們編寫的反射程序,可以大大優(yōu)化程序邏輯(訪問(wèn)受保護(hù)級(jí)別限制的代碼不在此范圍內(nèi))。

          上面代碼的優(yōu)化:


          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()); }


          通過(guò) dynamic 動(dòng)態(tài)類型對(duì)象 b 來(lái)調(diào)用反射得到對(duì)象的屬性、方法可直接調(diào)用,從而省去了頻繁的類型轉(zhuǎn)換操作。

          反射常見(jiàn)應(yīng)用場(chǎng)景

          應(yīng)用場(chǎng)景我印象最深刻的是 MS Petshop 示例,從SQL Server 數(shù)據(jù)庫(kù)切換到 oracle 數(shù)據(jù)庫(kù)時(shí)反射獲得不同的數(shù)據(jù)訪問(wèn)層。然我實(shí)際項(xiàng)目中從未遇到過(guò)中途切換數(shù)據(jù)庫(kù)的情況,其他應(yīng)用場(chǎng)景基本類似上面的示例。如果朋友你發(fā)現(xiàn)更多的應(yīng)用場(chǎng)景,請(qǐng)給予補(bǔ)充,3ks。

          反射的優(yōu)缺點(diǎn)

          優(yōu)點(diǎn):反射使程序更靈活

          缺點(diǎn):反射運(yùn)行速度相對(duì)較慢

          至于反射相比普通程序慢,我沒(méi)有進(jìn)行過(guò)測(cè)試也不打算進(jìn)行。現(xiàn)實(shí)情況是:Ms提倡使用 dynamic、Mvc流行、Ms對(duì)CLR不斷優(yōu)化、機(jī)器性能的提升,所以你在開(kāi)發(fā)中無(wú)需過(guò)多考慮反射的性能問(wèn)題。如果你寫的程序運(yùn)行速度出現(xiàn)了瓶頸(應(yīng)首先確保自己程序?qū)懙暮侠恚芯恳幌聰?shù)據(jù)庫(kù)優(yōu)化、數(shù)據(jù)緩存、web緩存、負(fù)載均衡等技術(shù)我認(rèn)為更實(shí)際一些。

          請(qǐng)放心大膽的使用反射技術(shù)吧,朋友!

          隨后我將寫一系列關(guān)于C# 異步編程的文章,感興趣的朋友請(qǐng)點(diǎn)下面的 “關(guān)注我” ,謝謝。

          作者:DW039
          出處:http://www.cnblogs.com/dw039


          支持小微:

          騰訊云 新年活動(dòng)!玩服務(wù)器的可以搞搞,老客戶也可以參加!

          輕量服務(wù)器??2核4G8M80G?222元/3年??

          爆款1核2G云服務(wù)器首年38元??

          鏈接:https://curl.qcloud.com/bR8ycXZa


          右下角,您點(diǎn)一下在看圖片5a789394e08e5a013cc4ea496d1fe5a8.webp

          小微工資漲1毛

          商務(wù)合作QQ:185601686



          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性,国产三级视频 | 波多野结衣一区久久在线观看 | 谁有毛片| 亚洲精品第一页 | 2024国产精品 |