C# 類相同屬性賦值

舒碧發表於2018-08-14

做專案時偶爾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));
        }

 

相關文章