C#秘密武器之反射——替換反射

來源:互聯網
上載者:User

標籤:

反射雖然有時很有必要,但是應用反射的代碼大多“複雜難懂”、“效能不高”,因此我們可以嘗試找尋在一些情境下替換反射的方法。此處也只是一些栗子,更多巧妙的應用還是自己以後親自查查~

使用普通反射完成的簡單Demo:

我們首先建立一個Person類,這個類非常簡單,一個Name的public屬性,一個_age的私人變數。完整代碼如下:

public class Person{      private readonly int _age;      public Person(int age)      {          _age = age;      }      public string Name { get; set; }      public bool GuessAge(int age)      {          return _age == age;      }}

接下來,看看常規的使用reflection擷取一個person對象公開屬性,私人變數同時調用對象的方法:

var type = p.GetType();var property = type.GetProperty("Name");//根據名稱擷取類型屬性Console.WriteLine(property.GetValue(p).ToString());//擷取對象的屬性值var field = type.GetField("_age", BindingFlags.NonPublic | BindingFlags.Instance);//擷取私人變數_age, 後面的BindingFlags非常重要,否則預設是不能夠取到private的東西Console.WriteLine(field.GetValue(p));var guessResult = type.InvokeMember("GuessAge", BindingFlags.InvokeMethod, null, p, new object[] { 20 });//調用對象的方法Console.WriteLine(guessResult);
 1. 使用PrivateObject

什麼是PrivateObject, PrivateObject是微軟在單元測試中引入的,本意是方便我們寫單元測試的時候,對於私人變數,方法,能夠非常簡單方便的調用。但是這也不妨礙我們在開發代碼中使用。使用PrivateObject只需要引用Microft.VisualStudio.QualityTools.UnitTestFramework

接下來看看,如何使用PrivateObject來實現:

var privateObject = new PrivateObject(p);Console.WriteLine(privateObject.GetProperty("Name"));Console.WriteLine(privateObject.GetField("_age"));Console.WriteLine(privateObject.Invoke("GuessAge", new object[] { 20 }));

上面的代碼和使用Reflection的效果完全一樣。是不是覺得整個世界都清淨許多。在代碼的可讀性上面,比Reflection好不少。

2. 使用dynamic

使用動態類型,可以非常簡單方便的訪問對象的屬性的方法,比如上面的代碼,如果我用dynamic實現:

dynamic person = p;Console.WriteLine(person.Name);//Console.WriteLine(person._age);Console.WriteLine(person.GuessAge(20));

使用dynamic的前提是,你在寫代碼的時候,就需要知道該對象的確切的屬性名稱字和方法名,不能作為參數傳遞。而上面的Refelction和PrivateObject是可以的。
使用dynamic還有一個缺點,就是無法訪問到對象的私人成員。這也是注釋掉_age輸出的原因。

真實的使用情境是,可以在不需要定義介面的情況下,實現通用的代碼。比如Person有個Start屬性, Car也有個Start屬性,有個功能是需要為由Start的東西,顯示的時候,都要帶個星星的表徵圖,這個時候,使用dynamic,就能夠寫出同時支援Person和Car的方法。

3. 使用Exposed

使用dynamic不能訪問私人成員的問題,在Exposed裡得到完全解決,從名字(翻譯成暴露)也能看出來,它就是幹這個的。

var exposedObj = Exposed.From(p);Console.WriteLine(exposedObj.Name);Console.WriteLine(exposedObj._age);Console.WriteLine(exposedObj.GuessAge(20));

Exposed是第三方開源的,項目地址是https://github.com/Cognifide/ExposedObject,也可以在nuget中下載到。

4. 大殺器Clay

看到上面的“廢話”,動態語言的愛好者只會冷笑一下,醜陋的靜態編譯語言,這些東西在動態語言裡面,“這都不是事”。好吧,我承認,但是看完了Clay,也許能改變你的看法。

dynamic New = new ClayFactory();var person = New.Person().Name("Louis")._age(30);person.GuessAge = new Func<int, bool>(x => x == person._age);Console.WriteLine(person.Name);Console.WriteLine(person._age);Console.WriteLine(person.GuessAge()(20));

 

C#秘密武器之反射——替換反射

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.