C#中屬性PropertyInfo的使用
常規屬性
常規屬性以前做Winform的時候經常使用,現在開始使用EF,基本上都是使用自動屬性,看下常規屬性的完成構成:
1.私有欄位,一般設定為私有,通過屬性來賦值保證起安全性:
private string _age;
2.get訪問器,負責讀取資料,其中可以進行自己的邏輯判斷和資料驗證,以return或者throw結束:
get { //年齡返回值判斷 return _age> 0 ? _age: 0; }
3.set訪問器,負責給屬性賦值,類似於一個返回型別為void的方法,可以包含邏輯處理,例如可以根據預設的值通過計算後返回結果。
自動屬性
上面簡單的說了一下常規屬性,當屬性訪問器中不需要其他邏輯時,可以使用自動屬性,不過需要注意一點的就是宣告自動屬性時,編譯器將建立一個私有的匿名後備欄位,該欄位只能通過屬性的 get 和 set 訪問器進行訪問。
public int Id { get; set; }
自動屬性沒有太多可以可以說的東西,簡單的對比一下常規屬性和自動屬性之間的區別吧:
1.自動實現的屬性必須同時宣告 get 和 set 訪問器。建立 readonly 自動實現屬性時,需要將set 訪問器設定為private。
2自動實現的屬性上可以使用特性,不能用在支援後備欄位上。 如果屬性的後備欄位上使用特性,則應該只建立常規屬性。
3.自動實現屬性get,和set中不能包含特殊的邏輯處理。與欄位類似,但不同於欄位。與欄位不同,屬性不作為變數來分類,不能將屬性作為 ref引數或 out引數傳遞。
屬性PropertyInfo的使用
上面大概簡單的說了一下屬性和自動屬性之間的區別,現在可以迴歸到文中最開始的時候的那個問題:
1.案例1,如果兩個類中有大部分的欄位相同,需要將其中一個類的欄位賦值給另外一個類:
定義Person類:
public class Person { public Person(int id,string name,string address) { this.Id = id; this.Name = name; this.Address = address; } publicint Id { get; set; } public string Name { get; set; } public string Address { get; set; } }
定義User類
public class User { public int Id { get; set; } public string Name { get; set; } public string Group { get; set; } }
轉換方法:
public static User ConvertObject(User user,Person person) { PropertyInfo[] userPro = user.GetType().GetProperties(); PropertyInfo[] personPro = person.GetType().GetProperties(); if (userPro.Length>0&&personPro.Length>0) { for (int i = 0; i < userPro.Length; i++) { for (int j = 0; j < personPro.Length; j++) {<br> //判斷User的屬性是不是的Person中 if (userPro[i].Name == personPro[j].Name && userPro[i].PropertyType == personPro[j].PropertyType) { Object value=personPro[j].GetValue(person, null); //將Person中屬性的值賦值給User<br> userPro[i].SetValue(user,value , null); } } } } return user; }
方法的呼叫:
static void Main(string[] args) { Person person = new Person(1,"FlyElephant","北京"); User user = new User(); user.Id = 20; user = ConvertObject(user, person); Console.WriteLine("Id:" + user.Id + "Name:" + user.Name + "角色:" + user.Group); System.Console.Read(); }
2.之前在做Winform的時候就經常回使用到SqlHelper,現在也有很多公司是這麼使用的,當時很多東西感覺就是重複性的操作,一度以為程式設計只是複製貼上,下面這段程式碼大家應該很常見:
List<Person> list = new List<Person>(); SqlDataReader sdr = new SqlDataReader(); while (sdr.Read()) { Person person = new Person(); person.Name = sdr.GetString(0); //....下面類似 list.Add(person); }
開始寫的時候覺得是鍛鍊了,寫的多了就覺得無聊了,其實完全可以換一種方式來實現上面的程式碼:
public static List<T> ConvertData<T>(SqlDataReader sdr) { List<T> list = new List<T>(); Type type = typeof(T); PropertyInfo[] properties = type.GetProperties(); while (sdr.Read()) { T model = Activator.CreateInstance<T>(); for (int i = 0; i < properties.Length; i++) { for (int j = 0; j < sdr.FieldCount; j++) { //判斷屬性的名稱和欄位的名稱是否相同 if (properties[i].Name == sdr.GetName(j)) { Object value =sdr[j]; //將欄位的值賦值給User中的屬性 properties[i].SetValue(model, value, null); } } } list.Add(model); } return list; }
List<User> list = new List<User>(); SqlDataReader sdr = cmd.ExecuteReader(); list = ConvertData<User>(sdr);
3.案例三,ajax頁面傳遞值可以使用get方式,或者post方式的傳遞JSON格式資料轉換
簡單的轉換一個get傳遞的字串Name=xx&Age=xx,後臺直接用一個字典去模擬了:
Dictionary<string, object> dic = new Dictionary<string, object>(); dic.Add("Id",100); dic.Add("Name", "keso"); dic.Add("Group", "程式設計師");
轉換字典方法:
public static T ConvertDic<T>(Dictionary<string, object> dic) { T model = Activator.CreateInstance<T>(); PropertyInfo[] modelPro = model.GetType().GetProperties(); if (modelPro.Length > 0 && dic.Count() > 0) { for (int i = 0; i < modelPro.Length; i++) { if (dic.ContainsKey(modelPro[i].Name)) { modelPro[i].SetValue(model, dic[modelPro[i].Name], null); } } } return model; }
最後的呼叫:
User user = ConvertDic<User>(dic);