【學習資料】
《C#圖解教程》(第24章):https://www.cnblogs.com/moonache/p/7687551.html
電子書下載:https://pan.baidu.com/s/1mhOmBG0
【內容】
對以下文章的整合:
知識點:
- 用途
- 命名空間
- 主要類: System.Type System.Reflection.Assembly
- System.Type類
- 說明
- 獲取給定類型的Type的3種方式
- Type類的 常用屬性
- Type類的 常用方法
- 用反射生成對象
- ConstructorInfo
- Activator.CreateInstance
- 使用Type反射舉例(創建對象、獲取並設置字段或屬性、調用方法)
- Assembly類
- 用途
- Assembly常用方法
- 使用舉例
- 擴展知識
- Assembly三種加載方式(Load、LoadFrom、LoadFile)的區別
【文章整合筆記】
-
- .NET的應用程序由幾個部分:程序集(Assembly)、模塊(Module)、類型(class)組成。
- 反射是.NET中的重要機制,通過反射,可以 在運行時,獲得程序或程序集中 每一個類型(包括類、結構、委托、接口和枚舉等)的 成員和成員的信息。
- 有了反射,即可對每一個類型了如指掌。另外我還可以直接創建對象,即使這個對象的類型在編譯時還不知道。
- 用途
- Assembly :定義和加載程序集,加載在程序集清單中列出模塊,以及從此程序集中查找類型並創建該類型的實例。
- Module :了解包含 模塊 的程序集以及模塊中的類等,還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。
- ConstructorInfo:了解 構造函數 的名稱、參數、訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等。
- ParameterInfo :了解 參數 的名稱、數據類型、是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。
- EventInfo :了解 事件 的名稱、事件處理程序數據類型、自定義屬性、聲明類型和反射類型等,添加或移除事件處理程序。
- FiedInfo :了解 字段 的名稱、訪問修飾符(如public或private)和實現詳細信息(如static)等,並獲取或設置字段值。
- PropertyInfo :了解 屬性 的名稱、數據類型、聲明類型、反射類型和只讀或可寫狀態等,獲取或設置屬性值。
- MethodInfo :了解 方法 的名稱、返回類型、參數、訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等。
- 用到的命名空間
- System.Reflection
- System.Type
- System.Reflection.Assembly
- 用到的主要類
- System.Type 類 // 通過這個類可以訪問任何給定數據類型的信息。
- System.Reflection.Assembly 類 // 它可以用於訪問給定程序集的信息,或者把這個程序集加載到程序中。
- System.Type類
- System.Type 類對於反射起着核心的作用
- 但它是一個抽象的基類,Type有與每種數據類型對應的派生類,我們使用這個派生類的對象的方法、字段、屬性來查找有關該類型的所有信息
- 程序中用到的每一個類型,CLR都會創建一個包含這個類型信息的Type類型的對象
- 程序中用到的每一個類型,都會關聯到獨立的Type類型的對象
- 不管創建的類型有多少個實例,只有一個Type對象會關聯到所有這些實例
- 獲取給定類型Type引用的 3種方式:
- typeof()
-
Type t = typeof(string);
- object.GetType()
-
string s = "hello"; Type t = s.GetType();
- Type.GetType() :類型的完整名稱(包含命名空間名)
-
Type t = Type.GetType("System.String");
-
- Type類的常用屬性 (以string為例)
- Type類的常用方法
- 注:只能獲取 public 的成員(字段、屬性、方法、事件、構造函數)
- 通過反射生成對象
- 用 ConstructorInfo 生成對象
-
System.Type t = typeof(string);
// 獲取參數為char[]的構造函數: string(char[]) System.Reflection.ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(char[]) });
// 等價於 object obj = new string( new char[] { 'h', 'e', 'l', 'l', 'o' } ) object obj = ci.Invoke(new object[] { new char[] { 'h', 'e', 'l', 'l', 'o' } });
-
- 用 Activator 生成對象
-
System.Type t = typeof(string);
// 等價於 object obj = new string( new char[] { 'h', 'e', 'l', 'l', 'o' } ) object obj2 = Activator.CreateInstance(t, new char[] { 'h', 'e', 'l', 'l', 'o' });
-
- 用 ConstructorInfo 生成對象
- 使用Type反射舉例(創建對象、獲取並設置字段或屬性、調用方法)
-
public class MyTest { // 字段 public int value1 = 1; private int value2 = 2; // 屬性 public string name1 { get; set; } = "hello"; protected string name2 { get; set; } = "world"; // 方法 public void Show1() { Debug.Log(name1 + value1); } internal void Show2() { Debug.Log(name2 + value2); } } void Start() { // 獲取 MyTest類 的 Type類型 Type t = typeof(MyTest); // 使用Activator創建對象 object obj = Activator.CreateInstance(t); // 獲取字段 FieldInfo obj_value1 = t.GetField("value1"); FieldInfo obj_value2 = t.GetField("value2"); // null,無法獲取 private 字段 // 獲取屬性 PropertyInfo obj_name1 = t.GetProperty("name1"); PropertyInfo obj_name2 = t.GetProperty("name2"); // null,無法獲取 protected 字段 // 獲取方法 MethodInfo obj_Show1 = t.GetMethod("Show1"); MethodInfo obj_Show2 = t.GetMethod("Show2"); // null,無法獲取 internal 字段 // 設置字段 SetValue obj_value1.SetValue(obj, 10); // 設置屬性 SetValue obj_name1.SetValue(obj, "heihei"); // 調用方法 Invoke obj_Show1.Invoke(obj, null); }
- 運行結果
-
- Assembly類
- 用途
- 使用Assembly類可以降低程序集之間的耦合,有利於軟件結構的合理化
- 獲得程序集的信息
- 動態的加載程序集
- 在程序集中查找類型信息
- 創建該類型的實例
- 常用的方法
- 使用舉例
-
namespace MyNameSpace { public class LearnCS : MonoBehaviour { public class MyTest { public class MySubTest { } } void Start() { // 加載程序集,獲取Assembly實例 Assembly ass1 = Assembly.Load("Assembly-CSharp"); Assembly ass2 = Assembly.LoadFrom("C:/E/Projects/Demo/Library/ScriptAssemblies/Assembly-CSharp.dll"); Assembly ass3 = Assembly.LoadFile("C:/E/Projects/Demo/Library/ScriptAssemblies/Assembly-CSharp.dll"); // 獲取MyTest類型所在的程序集Assembly Assembly ass = Assembly.GetAssembly(typeof(MyTest)); // 獲取當前運行的程序集Assembly Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取程序集名稱信息 string assembly_FullName = assembly.FullName; AssemblyName assembly_Name = assembly.GetName(); // 獲取程序集路徑 string assembly_CodeBase = assembly.CodeBase; string assembly_Location = assembly.Location; // 獲取Type Type[] types = assembly.GetTypes(); Type t = assembly.GetType("MyNameSpace.LearnCS+MyTest"); // 通過Type的FullName // 創建實例 var obj = assembly.CreateInstance("MyNameSpace.LearnCS+MyTest"); // 通過Type的FullName } } }
-
- 運行結果
【擴展知識】
- Assembly三種加載方式(Load、LoadFrom、LoadFile)的區別
-
- Load
- 使用 程序集名 加載,Load("xxx")
- 同時會 加載依賴 的其他程序集
- 效率最高,優先使用這個方式
- LoadFrom
- 使用 路徑 加載,LoadFrom("x/xx/xxx.dll")
- 可以通過URL加載("http://www.abc.com/test.dll"),會被下載到緩存文件中
- 同時會 加載依賴 的其他程序集
- 加載過的程序集,不會重新加載
- 不能用於加載標識相同但路徑不同的程序集
- LoadFile
- 使用 路徑 加載,LoadFile("x/xx/xxx.dll")
- 不會加載依賴 的程序集
- 可以多次加載同一個程序集
- 可以用來加載和檢查具有相同標識但位於不同路徑中的程序集,但不會加載程序的依賴項
- Load