如何在AutoMapper中处理自定义属性

我有一个ViewModel,它接受一些Model数据并略微改变它。

我这样做的方式“有效”,因为我只是将DomainModel传递给ViewModel的构造函数,但由于我在一些一对一的ViewModel上使用AutoMapper,我想我会尝试学习如何在所有ViewModel上进行映射。

这是ViewModel的一个例子,它可以做一些额外的工作。

 public class UsersDetailsViewModel { public string UserName { get; set; } public string Email { get; set; } public string Website { get; set; } public int ID { get; set; } public List OpenIds { get; set; } public string UserAge { get; set; } public string About { get; set; } public string Slug { get; set; } public System.DateTime LastSeen { get; set; } public string Region { get; set; } public string MemberSince { get; set; } public string Reputation { get; set; } public bool IsUserMatch { get; set; } private readonly MarkdownDeep.Markdown _markdown; public UsersDetailsViewModel(Domain.User user) { AuthUserData currentuser = AuthenticationHelper.RetrieveAuthUser; _markdown.NoFollowLinks = true; _markdown.SafeMode = true; _markdown.ExtraMode = false; _markdown.MarkdownInHtml = true; // We want to ensure that the user has a username, even if they // haven't set one yet. What this does is check to see if the // user.UserName field is blank, and if it is, it will set the // username to "UserNNNN" where NNNN is the user ID number. _UserName = (user.UserName != null) ? user.UserName : "User" + user.ID.ToString; // Nothing fancy going on here, we're just re-passing the object from // the database to the View. No data manipulation! _Email = user.Email; _Website = user.WebSite; _ID = user.ID; // Get's a list of all of the user's OpenID's _OpenIds = user.OpenIDs.ToList; // Converts the users birthdate to an age representation _UserAge = user.BirthDate.ToAge; //IE: 29 // Because some people can be real ass holes and try to submit bad // data (scripts and shitè) we have to modify the "About" content in // order to sanitize it. At the same time, we transform the Markdown // into valid HTML. The raw input is stored without sanitization in // the database. this could mean Javascript injection, etc, so the // output ALWAYS needs to be sanitized. // This method below was used in conjunction with MarkDownSharp // _About = Trim(Utilities.HtmlSanitizer.Sanitize(Markdown.Transform(user.About))) _About = _markdown.Transform(user.About); // Removes spaces from Usernames in order to properly display the // username in the address bar _Slug = Strings.Replace(user.UserName, " ", "-"); // Returns a boolean result if the current logged in user matches the // details view of tBhe user in question. This is done so that we can // show the edit button to logged in users. _IsUserMatch = (currentuser.ID == user.ID); // Grabs the users registration data and formats it to a  tag // for use with the timeago jQuery plugin _MemberSince = user.MemberSince; // Grabs the users last activity and formats it to a  tag // for use with the timeago jQuery plugin _LastSeen = user.ActivityLogs.Reverse.FirstOrDefault.ActivityDate; // Formats the users reputation to a comma Deliminated number // IE: 19,000 or 123k _Reputation = user.Reputation.ToShortHandNumber; // Get the name of the users Default Region. _Region = user.Region.Name.FirstOrDefault; } } 

这就是我目前如何使用上面的ViewModel

 public ActionResult Details(int id) { User user = _userService.GetUserByID(id); if (user != null) { Domain.ViewModels.UsersDetailsViewModel userviewmodel = new Domain.ViewModels.UsersDetailsViewModel(user); return View(userviewmodel); } else { // Because of RESTful URL's, some people will want to "hunt around" // for other users by entering numbers into the address. We need to // gracefully redirect them to a not found page if the user doesn't // exist. throw new ResourceNotFoundException(); } } 

在进行上面的自定义处理时,如何使用(或应该使用)AutoMapper将我的DomainModel映射到我的ViewModel?

在创建Map的automapper上,您可以为目标类型的特定成员指定其他进程。

那么你的默认地图就在哪里

 Mapper.Map(); 

有一个流畅的语法来定义更复杂的映射:

 Mapper.Map() .ForMember(vm=>vm.UserName, m=>m.MapFrom(u=>(u.UserName != null) ? u.UserName : "User" + u.ID.ToString())); 

这里ForMember接受两个Arguments,第一个定义您要映射到的属性。 第二种提供了定义映射的方法。 举个例子,我已经删除并显示了一个简单的映射。

如果您需要更困难的映射(例如您的CurrentUser映射),您可以创建一个实现IResolver接口的类,将您的映射逻辑合并到新的clases中,然后将其添加到映射中。

 Mapper.Map() .ForMember(vm=>vm.IsUserMatch, m=>m.ResolveUsing())); 

当Mapper进行映射时,它将调用您的自定义解析器。

一旦你发现了.ForMember方法的语法,其他所有插槽就到位了。

可以通过以下代码在global.ascx(启动时)中定义自定义映射:

  AutoMapper.Mapper.CreateMap() .ForMember(o => o.Email, b => b.MapFrom(z => z.Email)) .ForMember(o => o.UserName , b => b.MapFrom(user => (user.UserName != null) ? user.UserName : "User" + user.ID.ToString)); 

你可以通过BeforeMap()方法做一些初始化。 但您可能需要在viewmodel中进行一些更改。