具有复杂类型的AutoMapper

时间:2011-09-29 23:47:51

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

我在尝试使用AutoMapper的复杂类型时遇到问题。

我有两个对象,一个域和一个在我的视图中使用的ViewModel;

视图模型

public class RegisterCoupleModel
{
    [Required(ErrorMessage = "campo obrigatório")]
    [Display(Name = "Primeiro nome", Order = 0, GroupName = "Noivo")]
    [StringLength(60)]
    public string FistNameGroom
    {
        get;
        set;
    }

    [Required(ErrorMessage = "campo obrigatório")]
    [Display(Name = "Último nome", Order = 1, GroupName = "Noivo")]
    [StringLength(60)]
    public string LastNameGroom
    {
        get;
        set;
    }

    [Required(ErrorMessage = "campo obrigatório")]
    [RegularExpression(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$", ErrorMessage = "Formato de email inválido.")]
    [DataType(DataType.EmailAddress)]
    [Remote("IsEmailAvailable", "Validation", "", ErrorMessage = "este email já está sendo usado por outro usuário.")]
    [Display(Name = "Email", Order = 2, GroupName = "Noivo")]
    [StringLength(180)]
    public string EmailGroom
    {
        get;
        set;
    }

    [Required(ErrorMessage = "campo obrigatório")]
    [Display(Name = "Primeiro nome", Order = 0, GroupName = "Noiva")]
    [StringLength(60)]
    public string FistNameBride
    {
        get;
        set;
    }

    [Required(ErrorMessage = "campo obrigatório")]
    [Display(Name = "Último nome", Order = 1, GroupName = "Noiva")]
    [StringLength(60)]
    public string LastNameBride
    {
        get;
        set;
    }

    [Required(ErrorMessage = "campo obrigatório")]
    [RegularExpression(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$", ErrorMessage = "Formato de email inválido.")]
    [DataType(DataType.EmailAddress)]
    [Remote("IsEmailAvailable", "Validation", "", ErrorMessage = "este email já está sendo usado por outro usuário.")]
    [Display(Name = "Email", Order = 2, GroupName = "Noiva")]
    [StringLength(180)]
    public string EmailBride
    {
        get;
        set;
    }

    [Required(ErrorMessage = "campo obrigatório")]
    [Display(Name = "Url")]
    [RegularExpression(@"^[a-zA-Z0-9_\-\.\+]{5,22}$", ErrorMessage = "Chave inválida")]
    [StringLength(22, MinimumLength = 5, ErrorMessage = "A chave deve ter entre {0} e {1} caracteres.")]
    [Remote("IsKeywordAvaliable", "Validation")]
    public string UrlKeyword
    {
        get;
        set;
    }

    [Display(Name = "Voce é humano?")]
    [UIHint("ReCaptcha")]
    public string ReCaptcha
    {
        get;
        set;
    }
}

域对象

public class Couple
{
    [Key]
    public Guid Id { get; set; }
    public string UrlKeyword { get; set; }
    public virtual Partner Groom { get; set; }
    public virtual Partner Bride { get; set; }
    public DateTime Marriage { get; set; }
    public DateTime Dating { get; set; }
    public DateTime Engagement { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

如果您看,您会看到我的对象Couple域的属性包含BrideGroom,其实际上是相同类型

如何将我的域对象Couple映射到RegisterCoupleModel

在这里我做到了:

在设置中,automapper尝试执行以下操作:

CreateMap<RegisterCoupleModel, Couple>()
    .ForMember(dest => dest.Bride.User.FirstName, opt => opt.MapFrom(source => source.FistNameBride))
    .ForMember(dest => dest.Bride.User.LastName, opt => opt.MapFrom(source => source.LastNameBride))
    .ForMember(dest => dest.Bride.User.Email, opt => opt.MapFrom(source => source.EmailBride))
    .ForMember(dest => dest.Groom.User.FirstName, opt => opt.MapFrom(source => source.FistNameGroom))
    .ForMember(dest => dest.Groom.User.LastName, opt => opt.MapFrom(source => source.LastNameGroom))
    .ForMember(dest => dest.Groom.User.Email, opt => opt.MapFrom(source => source.EmailGroom));

但是会显示以下错误:

  

表达式'dest =&gt; dest.Bride.User.FirstName'必须解析为   顶级会员。参数名称:lambdaExpression

我知道这会尝试使用嵌套类型映射属性。

但是如何将RegisterCoupleModel映射到Couple,而BrideGroom这两个属性属于同一类型?

我发现question here on StackOverflow看起来像这样,但它帮助了我。

1 个答案:

答案 0 :(得分:2)

我要做的是封装 FirstNameBride LastNameBride EmailBride FirstNameGroom 的属性> LastNameGroom EmailGroom 为嵌套的viewmodel类型,假设为PersonDetails

public class PersonDetails
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public string Email { get; set; }
}

并相应地更新您的父虚拟机:

public class RegisterCoupleModel
{
   public PersonDetails GroomDetails { get; set; }
   public PersonDetails BrideDetails { get; set; }
}

然后,您可以提供从PersonDetailsUser的映射(或Groom.User的任何类型):

Mapper.CreateMap<PersonDetails,User>();

请注意我是如何获得如此明确的属性映射 - &gt;因为源和目标中的字段具有相同的名称,因此不需要显式映射。始终尽可能地尝试这样做。少代码 - &gt;更好的代码。

然后除上述映射外,只需执行以下操作:

Mapper.CreateMap<RegisterCoupleModel, Couple>();

AutoMapper会看到RegisterCoupleModel有两个PersonDetails个对象,看它已经有了映射定义,然后自动使用它。

那应该有用(我以前做过)。

您不应该总是使用平面视图模型,在必要时嵌套它们(例如重用字段)。