【问题标题】:Automapper flatten using createmapAutomapper 使用 createmap 展平
【发布时间】:2011-10-28 16:09:05
【问题描述】:

我有多个类需要映射为 1 个类:

这是我映射的来源(视图模型):

public class UserBM
{
    public int UserId { get; set; }

    public string Address { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string State { get; set; }

    public int CountryId { get; set; }
    public string Country { get; set; }
}

目标类是这样的(领域模型):

public abstract class User
{
    public int UserId { get; set; }

    public virtual Location Location { get; set; }
    public virtual int? LocationId { get; set; }
}

public class Location
{
    public int LocationId { get; set; }

    public string Address { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string State { get; set; }

    public virtual int CountryId { get; set; }
    public virtual Country Country { get; set; }

}

这是我的自动映射器创建地图当前的样子:

Mapper.CreateMap<UserBM, User>();

根据 automapper codeplex 网站上的文档,这应该是自动的,但它不起作用。 AddressAddress2 等仍然为空。我的 createmap 应该是什么样的?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 automapper


    【解决方案1】:

    原因是 AutoMapper 无法按照约定将所有这些平面字段映射到 Location 对象。

    您需要一个自定义解析器。

    Mapper.CreateMap<UserBM, User>()
       .ForMember(dest => dest.Location, opt => opt.ResolveUsing<LocationResolver>());
    
    public class LocationResolver : ValueResolver<UserBM,Location>
    {
       protected override Location ResolveCore(UserBMsource)
       {
           // construct your object here.
       }
    }
    

    但是我不喜欢这个。 IMO,更好的方法是将 ViewModel 中的这些属性封装到嵌套视图模型中:

    public class UserBM
    {
        public int UserId { get; set; }
        public LocationViewModel Location { get; set; }
    }
    

    那么你所要做的就是定义一个额外的地图:

    Mapper.CreateMap<User, UserBM>();
    Mapper.CreateMap<LocationViewModel,Location>();
    

    然后一切都会好起来的。

    您应该尽可能尝试使用 AutoMapper 约定。当然可以让您的 ViewModel 更具层次性,以匹配目的地层次结构。

    【讨论】:

      【解决方案2】:

      编辑奇怪的是你问了这个问题..似乎是同一个问题 - 我想我错过了什么......

      检查这个SQ Question

      *

      定义两个映射,都从同一个源映射到不同的 目的地

      *

      【讨论】:

      • 不同的问题,这个问题正好相反。
      【解决方案3】:

      我认为您需要在UserBM 上使属性名称类似于LocationAddressLocationAddress2 才能使它们的自动投影起作用,但我可能错了。

      查看他们在Flattening 上的页面,他们的属性名称有两个源的属性名称,就像我指出的那样。

      【讨论】:

        【解决方案4】:

        只需遵循目标类中的命名约定,并在地址属性前加上 Location,因为这是源类中的属性名称:

        public class UserBM
        {
            public int UserId { get; set; }
        
            public string LocationAddress { get; set; }
            public string LocationAddress2 { get; set; }
            public string LocationAddress3 { get; set; }
            public string LocationState { get; set; }
        
            public int CountryId { get; set; }
            public string Country { get; set; }
        }
        

        【讨论】:

        • 我完全按照你说的做了。除了将 Location 放在 CountryId 前面。尝试映射后仍然 user.Location 为空。
        • @Lolcoder,你在说什么user.Location?我认为您的源类型是User,而您的目标类型是UserBM (Mapper.CreateMap&lt;User, UserBM&gt;();)。不是吗?在这种情况下,您将拥有 userBM.LocationAddress, ...
        猜你喜欢
        • 2021-10-13
        • 2013-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多