做專案時偶爾B類賦值給A類,碰巧A和B型別很多屬性欄位名是一樣的,或者只是大小寫不一樣,這是可以利用泛型,反射來寫一個自動化賦值的方法。
下面方法不考慮大小寫不一樣的情況,如果要考慮,可以使用字串方法 ToUpper() 、ToLower() 後,對比欄位名是否一樣。
public class MapperModel { /// <summary> /// B物件相同屬性賦值給A物件, /// </summary> /// <typeparam name="A">型別A</typeparam> /// <typeparam name="B">型別B</typeparam> /// <param name="b">B物件</param> /// <returns>返回建立的新A物件</returns> public static A Mapper<A, B>(B b) { A a = Activator.CreateInstance<A>(); try { Type Typeb = b.GetType();//獲得型別 Type Typea = typeof(A); foreach (PropertyInfo bp in Typeb.GetProperties())//獲得型別的屬性欄位 { foreach (PropertyInfo ap in Typea.GetProperties()) { if (ap.Name == bp.Name)//判斷屬性名是否相同 { if (ap.GetSetMethod()!= null) { if (bp.GetGetMethod()!=null) { ap.SetValue(a, bp.GetValue(b, null), null);//獲得b物件屬性的值複製給a物件的屬性 } } } } } } } catch (Exception ex) { throw ex; } return a; } }
值得注意的地方,屬性到底有沒有Get或者Set方法 ?B屬性Set訪問器是非公共的或不存在 則會賦值時出現異常。同理:A屬性如果 Get 訪問器是非公共的或不存在,則取值時出現異常
因此上面使用了 GetSetMethod(),GetGetMethod()做判斷。如果Get 、Set 訪問器不能正常獲取,則返回為null。
感覺下面的程式碼寫法更可讀:省略了一個迴圈
/// <summary> /// 傳入型別B的物件b,將b與a相同名稱的值進行賦值給建立的a中 /// </summary> /// <typeparam name="A">型別A</typeparam> /// <typeparam name="B">型別B</typeparam> /// <param name="b">型別為B的引數b</param> /// <returns>拷貝b中相同屬性的值的a</returns> public static A MapperTwo<A, B>(B b) { A a = Activator.CreateInstance<A>(); try { Type Typeb = typeof(B);//獲得型別 Type Typea = typeof(A); foreach (PropertyInfo ap in Typea.GetProperties()) { System.Reflection.PropertyInfo bp = Typeb.GetProperty(ap.Name); //獲取指定名稱的屬性 if (bp != null) //如果B物件也有該屬性 { if (ap.GetSetMethod() != null) //判斷A物件是否有能用Set方法 { if (bp.GetGetMethod() != null) //判斷B物件是否有能用Get方法 { ap.SetValue(a, bp.GetValue(b, null), null);//獲得b物件屬性的值複製給a物件的屬性 } } } } } catch (Exception ex) { throw ex; } return a; }
估計我寫的就是下面的原理,序列化,反序列化,不區分大小寫。當然,不能否定上面的內容。
public static A MapperTwo<A, B>(B b) { return Newtonsoft.Json.JsonConvert.DeserializeObject<A>(Newtonsoft.Json.JsonConvert.SerializeObject(b)); }