用Reflection 或 AutoMapper 對應兩個Class欄位的值

用Reflection 或 AutoMapper 對應兩個Class欄位的值

假設今天有兩個類別 OldClass 與 NewClass

這兩個類別有差不多的欄位

想要將OldClass欄位的值,塞到NewClass欄位該怎麼做比較快呢?

如果欄位不多,最簡單的方法應該就是:

NewClass.xxx = OldClass.xxx  <=這樣了吧

但如果欄位有幾十幾百個,那不就key到手軟!?

所以這時候可以用reflection或是利用 automapper 來達成

首先先建立兩個不同的類別,但欄位幾乎一樣


  class OldClass
    {
        public Guid ID { get; set; }

        public string Title { get; set; }

        public int Price { get; set; }
    }

    class NewClass
    {
        public Guid ID { get; set; }

        public string Title { get; set; }

        public int Price { get; set; }

        //比OldClass多一個折扣價格的欄位
        public int DiscountPrice { get; set; }
    }

接著我用Console程式寫了一個範例


class Program
    {
        static void Main(string[] args)
        {
            NewClass n = new NewClass();

            //建立物件時直接將值塞入
            OldClass o = new OldClass() {                
                                          ID = Guid.NewGuid(),            
                                          Title = "Reflection",   
                                          Price = 350 
                                        };
            
            //等等拿來記時用
            Stopwatch sw = new Stopwatch();

            sw.Reset();
            sw.Start();

            #region Reflection
            //抓出NewClass所有屬性
            foreach (var newClassItem in n.GetType().GetProperties())
            {
                //抓出OldClass所有屬性
                foreach (var oldClassItem in o.GetType().GetProperties())
                {
                    //如果屬性一樣的話,就將值塞進NewClass的物件
                    if (newClassItem.Name == oldClassItem.Name)
                    {
                        newClassItem.SetValue(n, oldClassItem.GetValue(o, null)
                                              , null);
                        break;
                    }
                    //對折扣價格另外做判斷及處理
                    else if (newClassItem.Name == "DiscountPrice" && 
                             oldClassItem.Name == "Price")
                    {
                        newClassItem.SetValue(n, 
                                     ((int)oldClassItem.GetValue(o, null)) / 2,
                                            null);
                        break;
                    }
                }
            }
            #endregion
            sw.Stop();

            Print(n, sw);

            //重設物件
            n = null;

            sw.Reset();
            sw.Start();

            #region AutoMapper

            //這句話我自己想成定義兩物件要怎麼對應
            Mapper.CreateMap<OldClass, NewClass>()
                .ForMember(dest => dest.DiscountPrice,
                                   opt => opt.MapFrom(src => src.Price / 2));
               //.ForMember可以另外去處理名稱不同的屬性該怎麼對應
               //這個例子就是NewClass的DiscountPrice要對應到OldClass的Price除以2
            
            //定義完後就可以對應了
            n = Mapper.Map<OldClass, NewClass>(o);

            #endregion
            sw.Stop();


            Print(n,sw);

            Console.ReadKey();
        }

        public static void Print(NewClass n,Stopwatch sw)
        {
            foreach (var item in n.GetType().GetProperties())
            {
                Console.WriteLine("屬性名稱:{0},值:{1}", 
                                  item.Name,  
                                  item.GetValue(n, null));
            }
            Console.WriteLine("時間:{0}", sw.ElapsedMilliseconds.ToString());
        }           
     
}
 

看看結果:

image

可以看到兩種方法都可以達到同樣的效果。

 

參考資料:

我的Coding之路-用Reflection 或 AutoMapper 對應兩個Class欄位的值

http://automapper.codeplex.com/

[VS2010] ASP.NET MVC With AutoMapper + FullCalendar