反射 有關程式及其類型的數據被稱為元數據,保存在程式的程式集 一個運行的程式查看本身的元數據或者其他程式的元數據的行為叫反射 一遍下來啥都沒整明白?沒事,咱只是慣例行事,先放定義。 動態創建類並調用其方法 先拋開反射這些亂七八糟的東西,我們來想想看:當你打開了游戲充值頁面想要變強的時候,界面是不是有 ...
反射
有關程式及其類型的數據被稱為元數據,保存在程式的程式集
一個運行的程式查看本身的元數據或者其他程式的元數據的行為叫反射
一遍下來啥都沒整明白?沒事,咱只是慣例行事,先放定義。
動態創建類並調用其方法
先拋開反射這些亂七八糟的東西,我們來想想看:當你打開了游戲充值頁面想要變強的時候,界面是不是有很多個選項?支付寶付款,微信支付,銀行卡支付,應有盡有,反正只要你想掏錢,我們一定不會讓爺您這錢花不出去。
作為一個愛思考的程式員,在卡上數字減少的時候,你已經在面無表情的思考這個支付頁面背後的邏輯了。那怎麼做呢?最簡單的當然是寫 if
else
語句,他是第幾個radio你就調用哪個進行付款。
這樣做確實沒什麼問題,但會不會麻煩了一點?銀行支付那麼多個銀行,每增加一個就寫一句if
嗎?這就完全是體力活了,有沒有辦法可以省事一點呢?最好我說用支付寶付款就用支付寶付款,你別說,還真可以。
終於輪到我們的主角反射登場了!BCL聲明瞭一個Type
抽象類,使用Type
類的對象可以獲取到程式使用的類型信息。我們可以用GetType
或者typeof
運算符來獲取Type
對象。
Type類成員
Name 返回類型名字
Namespace 返回包含類型聲明的命名空間
Assembly 返回聲明類型的程式集
GetFields 返回類型的欄位列表
GetProperties 返回類型的屬性列表
GetMethods 返回類型的方法列表
我們從前端界面得知了要調用的類名,現在我們根據它的名字來創建實例並調用pay方法進行支付。
using System;
using System.IO;
using System.Reflection;
namespace Sample
{
class ZhiFuBao
{
public void Pay(string money)
{
Console.WriteLine($"使用支付寶支付{money}元");
}
}
class WeiXing
{
public void Pay(string money)
{
Console.WriteLine($"使用微信支付{money}元");
}
}
class Program
{
static void Main(string[] args)
{
//獲取命名空間
string nameSpace = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location);
//要調用的類名
string className = "ZhiFuBao";
Type type = Type.GetType(nameSpace + "." + className);
//生成實例
object obj = Activator.CreateInstance(type);
//獲取pay方法並調用
MethodInfo method = type.GetMethod("Pay");
method.Invoke(obj,new object[]{ "666" });
//調用微信支付
className = "WeiXing";
type = Type.GetType(nameSpace + "." + className);
obj = Activator.CreateInstance(type);
method = type.GetMethod("Pay");
method.Invoke(obj, new object[] { "666" });
/*
* 程式輸出結果為:
* 使用支付寶支付666元
* 使用微信支付666元
*/
}
}
}
怎麼樣?代碼是不是一下就少了很多,其實反射的功能遠不止這些。
依賴註入
我們還可以用別人封裝好的反射來實現依賴註入。駕駛員駕駛車輛,擁有私有屬性IVehicle
,Car和Tank類都實現了IVehicle介面。
class Program
{
static void Main(string[] args)
{
//註冊服務
var sc = new ServiceCollection();
sc.AddScoped(typeof(IVehicle), typeof(Car));
sc.AddScoped<Driver>();
var sp = sc.BuildServiceProvider();
var driver = sp.GetService<Driver>();
driver.Drive();
}
}
如果我們有一天要開坦克了,那麼也只需要把typeof(car)
換成Tank就行。
何為依賴註入呢?說的直白點,就是統一實例化對象,把他們都放在一個公共的容器里,誰要用就拿給誰。