本篇內容是特性和反射的最後一篇內容,前面三篇文章:
詳解C#特性和反射(一)
詳解C#特性和反射(二)
詳解C#特性和反射(三)
一、晚期繫結(Late Binding)是一種在編譯時不知道型別及其成員,而在執行時建立指定型別的例項並呼叫其成員的技術,使用名稱空間System中的Activator類來實現晚期繫結,例如:
Type myType = Type.GetType(myClassName); //首先獲取型別資訊 object myObj = Activator.CreateInstance(myType); //通過Activator根據型別資訊建立物件 //如果獲取的型別可以獲取到,即位於當前程式集,可以使用強制轉換或as運算子得到該型別的變數,然後直接呼叫該物件的成員: //MyClass myClass = (MyClass)myObj; //也可以使用CreateInstance的泛型過載方法直接獲取該型別的變數: //MyClass myClass = Activator.CreateInstance<MyClass>(); //如果獲取的型別不確定或當前程式編譯時並沒有引入該型別所在的名稱空間,則需要通過反射訪問該型別的成員: MethodInfo methodInfo = myType.GetMethod(methodName); //獲取型別中的方法資訊 methodInfo.Invoke(myObj, null); //呼叫型別中的無參例項方法
※靜態方法CreateInstance會呼叫匹配度最高的建構函式構建物件,例子中的CreateInstance(Type type)和CreateInstance<T>()只會呼叫目標型別中無參的公有建構函式,當目標型別中沒有無參的公有建構函式時會丟擲異常MissingMethodException;Activator類中提供多個CreateInstance的過載方法以呼叫不同的建構函式並傳入引數,這裡不再一一介紹,用到時檢視定義即可看到所有的方法宣告;
二、使用晚期繫結技術也會打破單例模式中的物件唯一性:
public class MyClass { public static MyClass Instace = new MyClass(); private MyClass() { Console.WriteLine("MyClass`s Constructor Execute."); } public int MyFiled; } public class Program { static void Main(string[] args) { Console.WriteLine("Access the static member Instace of MyClass."); MyClass.Instace.MyFiled = 10; Console.WriteLine("Use the Activator class to create instance of MyClass.");
//通過CreateInstance的過載方法呼叫目標型別的私有建構函式 MyClass myObj = (MyClass)Activator.CreateInstance(typeof(MyClass), true); Console.WriteLine($"Instace of MyClass`s MyFiled is {MyClass.Instace.MyFiled}, myObj`s MyFiled is {myObj.MyFiled}."); Console.Read(); } }
輸出結果為(在.Net Core下執行,不同平臺下靜態成員的初始化時機略有不同,會導致這裡第一行和第二行輸出順序不一致):
Access the static member Instace of MyClass.
MyClass`s Constructor Execute.
Use the Activator class to create instance of MyClass.
MyClass`s Constructor Execute.
Instace of MyClass`s MyFiled is 10, myObj`s MyFiled is 0.
因此在使用單例模式時,應當避免使用晚期繫結建立物件,而應使用反射獲取單例中的靜態成員Instance;
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的認可是我寫作的最大動力!
作者:Minotauros
出處:https://www.cnblogs.com/minotauros/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。