在上一篇文章「AutoMapper - Complex Type 的資料對映」裡說明了幾種對於 Complex Type 的資料對映方式,其實還有一種方式,AutoMapper 提供了一種「Custom value resolvers(自定義值解析器)」,讓我們可以另外定義資料解析以及轉換的方式,以彈性的方式進行目標類別物件的資料對映。
這篇文章將會以前篇文章的程式來做示範。
下面是前一篇文章裡的程式,其中針對 ComplexModel 類別裡的 OrderModel 屬性有做資料對映的設定,
我必須說這程式的作法並不是很好,雖然我們在取得 Customer 資料時有特別過濾了是否有訂單資料的條件,但是這樣的做法式很有針對性的,是因為為了要讓程式看起來合理且不會發生錯誤,另外在設定資料對映的地方也是一樣,因為已經知道在取得資料時就已經會做一層過濾,所以不怕會有例外(Exception)的發生,所以就直接去取出第一筆訂單資料的值來做對映。
另外就是在做資料對映設定的部份,將全部的資料對映做一次性的設定,這樣的作法看起來好像結構比較完整,但是遇到比較特殊的對映設定時就會變得複雜,而且如果同樣的資料對映設定在其他的 Complex Type 也有的話,那是否就表示在其他地方又要重複的出現一樣的程式呢?
AutoMapper Wiki - Custom value resolvers
在上面說明「Custom value resolvers」的連結裡可以看到,我們可以建立自定義 ValueResolver 類別,然後在 ResolveCore 方法裡進行資料對映的處理,而原本的 Mapper.CreateMap 設定裡只需使用 ResolveUsing 指定的 ValueResolver 類別與要進行對映轉換的原始資料就可以,而且建立的 ValueResolver 類別也可以在其他的資料對映設定重複使用。
首先建立 Customer ValueResolver 類別,要繼承「ValueResolver<TSource, TDestination>」類別,並且覆寫 ResolveCore 方法,在 ResolveCore 方法裡做資料對映的處理,
而原本 Mapper.CreateMap 設定裡,對於目標類別 ComplexModel 的 OrderModel 屬性的對映設定就是使用 ResolveUsing 並且指定使用 OrderModelResolver 類別,最後記得指定要進行資料對映的原始資料,
執行結果
接著我們可以將資料對映的設定從 Controller 裡抽離出來,使用之前文章「AutoMapper 的設定 (Configuration)」的內容,將設定放到 AutoMapperConfig.cs 內容,讓 Controller 與資料對映設定的程式不要混雜在一起而有所區隔。
AutoMapperConfig.cs
public class AutoMapperConfig
{
public static void Configure()
{
Mapper.Initialize(x =>
{
x.AddProfile<ComplexModelProfile>();
});
}
public class ComplexModelProfile : Profile
{
public override string ProfileName
{
get
{
return "ComplexModelProfile";
}
}
protected override void Configure()
{
Mapper.CreateMap<Customer, ComplexModel>()
.ForMember(d => d.CustomerID, o => o.MapFrom(s => s.CustomerID))
.ForMember(d => d.Customer, o => o.MapFrom(s => s))
.ForMember(
d => d.OrderModel,
o => o.ResolveUsing<OrderModelResolver>()
.FromMember(s => s.Orders));
}
public class OrderModelResolver
: ValueResolver<ICollection<Order>, OrderModel>
{
protected override OrderModel ResolveCore(ICollection<Order> source)
{
if (!source.Any())
{
return null;
}
var order = source.OrderBy(x => x.OrderID).FirstOrDefault();
var dest = new OrderModel()
{
OrderID = order.OrderID,
OrderDate = order.OrderDate
};
return dest;
}
}
}
}
記得要在 Global.asax 的 Application_Start() 方法裡加入 AutoMapperConfig.Configure();
最後原本 Contoller 裡的程式因為將資料對映設定的內容放到 AutoMapperConfig.cs 內,所以程式就只會剩下取得資料以及資料對映的部份,最後的執行結果仍然一樣,
可以跟之前的程式做個比對,
善用 Custom Value Resolver 讓複雜的資料對映設定另外處理,此外也可以在不同的資料對映設定裡重複使用,並且將程式流程內的程式抽離出來,讓各自的程式有所區隔以及責任區分,如此一來程式就會比較好維護。
以上
沒有留言:
張貼留言