標籤:
前言:使用反射也有幾年了,但是一直覺得,反這個概念很抽象,今天有時間就來總結下這個知識點。
1、為什麼需要反射:
最初使用反射的時候,作為小菜總是不理解,既然可以通過new 一個對象的方式得到對象,然後通過對象去調用屬性和方法,那麼為什麼還需要反射去調用呢?後來使用多了發現這就是一個先綁定還是後綁定的問題,很多初使用反射的開發人員通常都會有類似這種疑慮:既然在開發時就能夠寫好代碼,幹嘛還放到運行期去做,不光繁瑣,而且效率也受影響。博主覺得主要是適用性的問題,如果你的系統沒有那麼高的擴充性和靈活性要求,你大可不必考慮反射。但在架構設計時,很多東西都需要考慮複用性,並且在某些特定的情境下你得不到具體的類時,你就必須用到反射。博主總結了下自己使用過的反射情境:
(1)有時不知道具體的類型,可以通過dll去得到類的對象;
(2)某些特殊方法,傳過來的是泛型類,需要通過反射處理某些特殊的業務;
(3)通用方法DataTable和List<T>的相互轉化時需要用到反射;
2、如何使用反射:
(1)反射dll得到類成員:
在一個未知的dll裡面有一個Person類
public class Person { private string address; private string email; public string Name { set; get; } public int Age { set; get; } public void SayHello() { Console.WriteLine("你好"); } public static string MystaticPro { set; get; } public static void MyStatic() { Console.WriteLine("我是static方法"); } }
通過反射dll得到Person類
static void Main(string[] args) { //反射dll var strDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dll\\ReflectorDLL.dll"); var oAssembly = Assembly.LoadFile(strDllPath); var lstTypes = oAssembly.GetTypes(); foreach (var oType in lstTypes) { if (oType.Name == "Person") { //預設得到類下面的所有public成員 var lstMembers = oType.GetMembers(); foreach (var oMem in lstMembers) { Console.WriteLine("GetMembers()方法得到的成員名稱:"+oMem.Name); } Console.WriteLine(""); //預設得到類下面的所有public屬性 var lstProperty = oType.GetProperties(); foreach (var oProp in lstProperty) { Console.WriteLine("GetProperties()方法得到的成員名稱:" + oProp.Name); } Console.WriteLine(""); //預設得到類下面的所有public欄位 var lstField = oType.GetFields(); foreach (var oField in lstField) { Console.WriteLine("GetFields()方法得到的成員名稱:" + oField.Name); } } } Console.ReadKey(); }
得到結果
(2)反射對象的私人成員:
一般私人屬性的用法比較少,我們就以私人欄位為例來說明,還是上面的例子:
static void Main(string[] args) { //反射dll var strDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dll\\ReflectorDLL.dll"); var oAssembly = Assembly.LoadFile(strDllPath); var lstTypes = oAssembly.GetTypes(); foreach (var oType in lstTypes) { if (oType.Name == "Person") { //預設得到類下面的所有public欄位 var lstField = oType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance); foreach (var oField in lstField) { Console.WriteLine("GetFields()方法得到的成員名稱:" + oField.Name); } } } Console.ReadKey(); }
(3)反射對象的靜態成員:
static void Main(string[] args) { //反射dll var strDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dll\\ReflectorDLL.dll"); var oAssembly = Assembly.LoadFile(strDllPath); var lstTypes = oAssembly.GetTypes(); foreach (var oType in lstTypes) { if (oType.Name == "Person") { //預設得到類下面的所有public成員 var lstMembers = oType.GetMembers(BindingFlags.Public|BindingFlags.Static); foreach (var oMem in lstMembers) { Console.WriteLine("GetMembers()方法得到的成員名稱:" + oMem.Name); } Console.WriteLine(""); //預設得到類下面的所有public欄位 var lstField = oType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance); foreach (var oField in lstField) { Console.WriteLine("GetFields()方法得到的成員名稱:" + oField.Name); } } } Console.ReadKey(); }
還有枚舉類型等等就不一一介紹了,基本上都是在BindingFlags這個上面做處理。
(4)反射得到對象以及對象的操作:
反射得到對象的方法主要有兩種
public static T GetModel<T>(T oModel) { var model = default(T) ; //得到對象的方法一: model = (T)typeof(T).GetConstructor(new System.Type[] { }).Invoke(new object[] { });//反射得到泛型類的實體 //得到對象的方法二: model = (T)Activator.CreateInstance(typeof(T)); //邏輯處理...... return model; }
對象屬性的取值和賦值:
//List集合轉換為DataTable public static DataTable ListFillTable(object obj) { if (!(obj is IList)) { return null; } var objlist = obj as IList; if (objlist == null || objlist.Count <= 0) { return null; } var tType = objlist[0]; DataTable dt = new DataTable(tType.GetType().Name); DataColumn column; DataRow row; System.Reflection.PropertyInfo[] myPropertyInfo = tType.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var t in objlist) { if (t == null) { continue; } row = dt.NewRow(); for (int i = 0, j = myPropertyInfo.Length; i < j; i++) { System.Reflection.PropertyInfo pi = myPropertyInfo[i]; string name = pi.Name; if (dt.Columns[name] == null) { var coltype = pi.PropertyType; if (coltype.Name == "Nullable`1") { //coltype = typeof(System.DBNull); column = new DataColumn(name); } else { column = new DataColumn(name, coltype); } dt.Columns.Add(column); } row[name] = pi.GetValue(t, null); } dt.Rows.Add(row); } return dt; }
C#基礎系列——反射筆記