如何处理AutoMapper自定义属性 [英] How to handle custom Properties in AutoMapper

查看:356
本文介绍了如何处理AutoMapper自定义属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个视图模型,需要一些模型数据和略微改变它。

I've got a ViewModel that takes some Model data and slightly alters it.

我在做它的方式作品,因为我只是通过了的DomainModel 来的构造函数视图模型,但因为我使用了一些我的一比一的ViewModels的AutoMapper,我想我会尝试并学习如何在所有的ViewModels进行映射。

The way I'm doing it "works" since I just pass the DomainModel to the constructor for the ViewModel, but since I'm using AutoMapper on some of my one-to-one ViewModels, I thought I'd try and learn how to do the mapping across all ViewModels.

下面是做了一点额外的一个视图模型的例子。

Here's an example of a ViewModel that does a little extra.

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<OpenID> 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 <time> tag
        // for use with the timeago jQuery plugin
        _MemberSince = user.MemberSince;

        // Grabs the users last activity and formats it to a <time> 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;
    }

}

这就是我目前使用上述视图模型

And here's how I currently utilize the above 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映射到我的视图模型,而这样做,你在上面看到的自定义处理?

How can I use (or should I use) AutoMapper to map my DomainModel to my ViewModel while doing the custom processing you see above?

推荐答案

在创建地图automapper可以指定目标类型的特定成员的附加进程。

On automapper where you create the Map you can specify additional processes for specific members of the destination type.

那么,你的默认的地图将

So where your default map would be

Mapper.Map<Domain.User, UsersDetailsViewModel>();

有能说一口流利的语法来定义更为复杂的映射:

there is a fluent syntax to define the more complicated mappings:

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

下面的ForMember需要两个参数,第一个定义了你映射到该属性。第二提供了限定的映射的装置。对于一个例子,我已经copped出来,容易映射的一个图所示。

Here the ForMember takes two Arguments the first defines the property that you are mapping to. The second provides a means of defining the mapping. For an example I have copped out and shown one of the easy mappings.

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

If you require a more difficult mapping, (such as your CurrentUser mapping) you can create a class that implements the IResolver interface, incorporate your mapping logic in that new clases and then add that into the mapping.

Mapper.Map<Domain.User, UsersDetailsViewModel>()
  .ForMember(vm=>vm.IsUserMatch, m=>m.ResolveUsing<MatchingUserResolver>()));

在映射来进行映射,将调用您的自定义解析器。

when Mapper comes to do the mapping it will invoke your custom resolver.

一旦你发现了.ForMember方法一切样槽的语法到位。

Once you discover the syntax of the .ForMember method everything else kind of slots into place.

这篇关于如何处理AutoMapper自定义属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆