我需要在平面ViewModel和深層結構化域模型之間映射兩種方法。這將是我們解決方案中的常見情況。AutoMapper:域模型和視圖模型之間的雙向深度映射
我的車型有:
public class Client
{
...
public NotificationSettings NotificationSettings { get; set; }
public ContactDetails ContactDetails { get; set; }
...
}
public class NotificationSettings
{
...
public bool ReceiveActivityEmails { get; set; }
public bool ReceiveActivitySms { get; set; }
...
}
public class ContactDetails
{
...
public string Email { get; set }
public string MobileNumber { get; set; }
...
}
public class ClientNotificationOptionsViewModel
{
public string Email { get; set }
public string MobileNumber { get; set; }
public bool ReceiveActivityEmails { get; set; }
public bool ReceiveActivitySms { get; set; }
}
映射代碼:
Mapper.CreateMap<Client, ClientNotificationOptionsViewModel>()
.ForMember(x => x.ReceiveActivityEmails, opt => opt.MapFrom(x => x.NotificationSettings.ReceiveActivityEmails))
.ForMember(x => x.ReceiveActivitySms, opt => opt.MapFrom(x => x.NotificationSettings.ReceiveActivitySms))
.ForMember(x => x.Email, opt => opt.MapFrom(x => x.ContactDetails.Email))
.ForMember(x => x.MobileNumber, opt => opt.MapFrom(x => x.ContactDetails.MobileNumber));
// Have to use AfterMap because ForMember(x => x.NotificationSettings.ReceiveActivityEmail) generates "expression must resolve to top-level member" error
Mapper.CreateMap<ClientNotificationOptionsViewModel, Client>()
.IgnoreUnmapped()
.AfterMap((from, to) =>
{
to.NotificationSettings.ReceiveActivityEmail = from.ReceiveActivityEmail;
to.NotificationSettings.ReceiveActivitySms = from.ReceiveActivitySms;
to.ContactDetails.Email = from.Email;
to.ContactDetails.MobileNumber = from.MobileNumber;
});
...
// Hack as ForAllMembers() returns void instead of fluent API syntax
public static IMappingExpression<TSource, TDest> IgnoreUnmapped<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
{
expression.ForAllMembers(opt => opt.Ignore());
return expression;
}
我不喜歡它,因爲:
1)它是繁瑣
2)第二映射幾乎拆除Automapper的功能並手動實現工作 - 它的唯一優勢是i小號參考Automapper整個代碼
任何人都可以提出的一致性:
a)一個更好的方式來使用Automapper深屬性?
b)更好的方式來執行這樣的雙向映射?
c)在這種情況下是否應該打擾使用Automapper的建議?是否有一個令人信服的理由不會恢復到手動編碼的簡單方法?例如:
void MapManually(Client client, ClientNotificationOptionsViewModel viewModel)
{
viewModel.Email = client.ContactDetails.Email;
// etc
}
void MapManually(ClientNotificationOptionsViewModel viewModel, Client client)
{
client.ContactDetails.Email = viewModel.Email;
// etc
}
-Brendan
附:重構領域模型不是解決方案。
P.P.S通過擴展方法&可以清理上面的代碼來設置深層屬性...但我寧願使用automapper功能。
你能分享你的ViewModel和Domain類的代碼嗎?有理由使用AfterMap而不是ForMember? – thepirat000
這只是示例代碼,但我添加了域/視圖模型類。我使用AfterMap而不是ForMember()來避免「表達式必須解析爲頂級成員」錯誤。 –
AutoMapper從來沒有用於這種情況,可能永遠不會。不要爲此使用它。 –