1. 程式人生 > >8分鐘學會使用AutoMapper

8分鐘學會使用AutoMapper

logs uget 領域 src 就是 不能 ret har create

一.什麽是AutoMapper與為什麽用它。

它是一種對象與對象之間的映射器,讓AutoMapper有意思的就是在於它提供了一些將類型A映射到類型B這種無聊的實例,只要B遵循AutoMapper已經建立的慣例,那麽大多數情況下就可以進行相互映射了。

二.如何使用?

直接nuget install-package automapper 簡單到不能再簡單了。

三.入門

定義了連個簡單的Model:

  public class Destination
    {
        public string name { get; set; }
        public string InfoUrl { get; set; }
    }

public class Source
    {
        public string name { get; set; }
        public string InfoUrl { get; set; }
        public string aa { get; set; }
    }
static void Main(string[] args)
        {
            Destination des = new Destination()
            {
                InfoUrl = "www.cnblogs.com/zaranet",
                name ="張子浩"
            };
            Mapper.Initialize(x => x.CreateMap<Destination, Source>());
            Source source = AutoMapper.Mapper.Map<Source>(des);
            Console.WriteLine(source.InfoUrl);
        }

  Initialize方法是Mapper的初始化,裏面可以寫上CreateMap表達式,具體是誰和誰進行匹配。在之後就可以直接進行一個獲取值的過程了,非常的簡單。

四.映射前後操作

偶爾有的時候你可能需要在映射的過程中,你需要執行一些邏輯,這是非常常見的事情,所以AutoMapper給我們提供了BeforeMap和AfterMap兩個函數。

Mapper.Initialize(x => x.CreateMap<Destination, Source>().BeforeMap(
                (src,dest)=>src.InfoUrl ="https://"+src.InfoUrl).AfterMap(
                (src,dest)=>src.name="真棒"+src.name));

其中呢,src是Destination對象,dest是Source,你呢就可以用這兩個對象去獲取裏面的值,說白了這就是循環去找裏面的值了。

五.條件映射

Mapper.Initialize(x => x.CreateMap<Destination, Source>().ForMember(dest => dest.InfoUrl,opt => opt.Condition(dest => dest.InfoUrl == "www.cnblogs.com/zaranet1")).ForMember(...(.ForMember(...))));

在條件映射中,通過ForMember函數,參數是一個委托類型Fun<>,其裏面呢也是可以進行嵌套的,但一般來說一個就夠用了。

六.AutoMapper配置

初始化配置是非常受歡迎的,每個領域都應該配置一次。

//初始化配置文件
Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Aliens, Person>();
});

 但是像這種情況呢,如果是多個映射,那麽我們只能用Profile來配置,組織你的映射配置,並將配置放置到構造函數中(這種情況是5.x以上的版本),一個是以下的版本,已經被淘汰了。

5.0及以上版本:

public class AliensPersonProfile : Profile
    {
        public AliensPersonProfile()
        {
            CreateMap<Destination, Source>();
        }
    }

5.0以下版本(在早期版本中,使用配置方法而不是構造函數。 從版本5開始,Configure()已經過時。 它將在6.0中被刪除。)

 public class OrganizationProfile : Profile
 {
     protected override void Configure()
     {
         CreateMap<Foo, FooDto>();
     }
 }

 然後在程序啟動的時候初始化即可。

Mapper.Initialize(x=>x.AddProfile<AliensPersonProfile>());

七.AutoMapper的最佳實踐

上文中已經說到了AutoMapper的簡單映射,但是在實際項目中,我們應該有很多類進行映射,這麽多的映射應該怎麽組織,這是一個活生生的問題,這成為主映射器。

在主映射器中,組織了多個小映射器,Configuration為我們的靜態配置入口類;Profiles文件夾為我們所有Profile類的文件夾。如果是MVC,我們需要在Global中調用,那我的這個是控制臺的。

public static void Configure()
        {
            Mapper.Initialize(cfg =>
            {
                cfg.AddProfile<DestinationSourceProfile>();
                cfg.AddProfile(new StudentSourceProfile());
            });
        }

其中添加子映射,可以用以上兩種方式。

public void Configuration(IAppBuilder app)
        {
            AutoMapperConfiguration.Configure();
        }

八.指定映射字段

在實際業務環境中,你不可能說兩個類的字段是一 一 對應的,這個時候我們就要對應它們的映射關系。

public class CalendarEvent
{
    public DateTime Date { get; set; }
    public string Title { get; set; }
}

public class CalendarEventForm
{
    public DateTime EventDate { get; set; }
    public int EventHour { get; set; }
    public int EventMinute { get; set; }
    public string DisplayTitle { get; set; }
}

在這兩個類中,CalendarEvent的Date將被拆分為CalendarEventForm的日期、時、分三個字段,Title也將對應DisplayTitle字段,那麽相應的Profile定義如下:

 public class CalendarEventProfile : Profile
    {
        public CalendarEventProfile()
        {
            CreateMap<CalendarEvent, CalendarEventForm>()
           .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.Date.Date))
           .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.Date.Hour))
           .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.Date.Minute))
           .ForMember(dest => dest.DisplayTitle, opt => opt.MapFrom(src => src.Title));
        }
    }

main方法通過依賴註入,開始映射過程,下圖是代碼和圖。

static void Main(string[] args)
        {
            CalendarEvent calendar = new CalendarEvent()
            {
                Date = DateTime.Now,
                Title = "Demo Event"
            };
            AutoMapperConfiguration.Configure();
            CalendarEventForm calendarEventForm = Mapper.Map<CalendarEventForm>(calendar);
            Console.WriteLine(calendarEventForm);
        }    

  技術分享圖片

那麽最後呢,如果是反向的映射,一定回缺少屬性,那麽就你就可以obj.屬性進行賦值。

附AutoHelper封裝類

/// <summary>
    /// AutoMapper擴展幫助類
    /// </summary>
    public static class AutoMapperHelper
    {
        /// <summary>
        ///  類型映射
        /// </summary>
        public static T MapTo<T>(this object obj)
        {
            if (obj == null) return default(T);
            Mapper.CreateMap(obj.GetType(), typeof(T));
            return Mapper.Map<T>(obj);
        }
        /// <summary>
        /// 集合列表類型映射
        /// </summary>
        public static List<TDestination> MapToList<TDestination>(this IEnumerable source)
        {
            foreach (var first in source)
            {
                var type = first.GetType();
                Mapper.CreateMap(type, typeof(TDestination));
                break;
            }
            return Mapper.Map<List<TDestination>>(source);
        }
        /// <summary>
        /// 集合列表類型映射
        /// </summary>
        public static List<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
        {
            //IEnumerable<T> 類型需要創建元素的映射
            Mapper.CreateMap<TSource, TDestination>();
            return Mapper.Map<List<TDestination>>(source);
        }
        /// <summary>
        /// 類型映射
        /// </summary>
        public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
            where TSource : class
            where TDestination : class
        {
           if (source == null) return destination;
            Mapper.CreateMap<TSource, TDestination>();
            return Mapper.Map(source, destination);
        }
        /// <summary>
        /// DataReader映射
        /// </summary>
        public static IEnumerable<T> DataReaderMapTo<T>(this IDataReader reader)
        {
            Mapper.Reset();
            Mapper.CreateMap<IDataReader, IEnumerable<T>>();
            return Mapper.Map<IDataReader, IEnumerable<T>>(reader);
        }
    }
}

8分鐘學會使用AutoMapper