自动映射,将单个目标属性映射为多个源属性的串联

K R*_*mar 6 automapper automapper-3

我有一种情况,我需要根据某些条件将单个属性映射为多个源属性的组合.

目的地:

public class Email
{
    public Email() {
        EmailRecipient = new List<EmailRecipient>();
    }
    public string Subject{get; set;}
    public string Body {get; set;}
    public virtual ICollection<EmailRecipient> EmailRecipient { get; set; } 
}

public class EmailRecipient
{
    public int EmaiId { get; set; }
    public string RecipientEmailAddress { get; set; }
    public int RecipientEmailTypeId { get; set; }
    public virtual Email Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

资源:

public class EmailViewModel
{
    public List<EmailRecipientViewModel> To { get; set; }
    public List<EmailRecipientViewModel> Cc { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
}

public class EmailRecipientViewModel
{
    public string RecipientEmailAddress { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想要 Mapper.Map<EmailViewModel,Email>()

在这里,我想我的地图Email.EmailRecipient作为组合EmailViewModel.ToEmailViewModel.Cc.然而,条件是,Email.EmailRecipient.RecipientEmailTypeId将1对和2 抄送

希望我的问题很明确.

Thi*_* Sá 5

实现此目的的一种可能方法是创建一个使用特定方法进行此转换的地图。地图创建将是:

Mapper.CreateMap<EmailViewModel, Email>()
    .ForMember(e => e.EmailRecipient, opt => opt.MapFrom(v => JoinRecipients(v)));
Run Code Online (Sandbox Code Playgroud)

JoinRecipients方法将在哪里执行转换本身。一个简单的实现可能是这样的:

private ICollection<EmailRecipient> JoinRecipients(EmailViewModel viewModel) {
    List<EmailRecipient> result = new List<EmailRecipient>();
    foreach (var toRecipient in viewModel.To) {
        result.Add(new EmailRecipient {
            RecipientEmailTypeId = 1, 
            RecipientEmailAddress = toRecipient.RecipientEmailAddress
        });
    }

    foreach (var ccRecipient in viewModel.Cc) {
        result.Add(new EmailRecipient {
            RecipientEmailTypeId = 2,
            RecipientEmailAddress = ccRecipient.RecipientEmailAddress
        });
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)


C B*_*uer 5

我是转换器的强烈反对者,主要是因为对于项目中的其他人来说,在映射调用之后事情就会“像魔术一样”发生。

处理此问题的一种更简单的方法是将属性实现为将视图模型上的其他属性转换为所需格式的方法。例子:

public class EmailViewModel
{
    public ICollection<EmailRecipient> EmailRecipient { 
        get {
             return To.Union(Cc);
        } 
    }
    public List<EmailRecipientViewModel> To { get; set; }
    public List<EmailRecipientViewModel> Cc { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,自动映射器会自动从 EmailRecipient 属性映射到 EmailRecipient 属性,如果有人试图弄清楚它是如何发生的,他们只需要查看视图模型即可。

几年后编辑此内容:作为一个警告,这样做意味着每次调用 EmailRecipient 时,您都会承担联合 和To字段的 o(n) 任务Cc。如果您只处理一封电子邮件,这很好,但如果您重用视图模型,并且有人将其与系统中的所有其他电子邮件循环在一起,则可能会产生巨大的性能问题。在这种情况下,我会采用已接受的答案,以便您避免这种潜在的性能陷阱。