c# - 如何使用自动映射器将简单的 poco 映射到复杂的对象层次结构?

标签 c# automapper

我有一个简单的 poco,需要映射到使用复杂对象层次结构的第三方提供的对象。如果可能的话,我想使用 AutoMapper,但我不确定如何正确设置它。

我在下面提供了一个简化的示例来展示我正在尝试做的事情。

我的poco:

public class Person
{
    public string FirstName { get; set; }
    public string Lastname { get; set; }
    public string FullName { get { return Firstname + " " + Lastname; } }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public string Postcode { get; set; }
    public string Reference { get; set; }
}

第三方对象

public class People
{
    public Person[] Person { get; set; }
}

public class Person
{
    public Names Names { get; set; }
    public Address Address { get; set; }
    public ReasonsForRequest[] Reasons { get; set; }
}

public class Names
{
    public string Fullname { get; set; }
}

public class Address
{
    public string AddressLine[] { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public string Postcode { get; set; }
}

public class ReasonsForRequest
{
    public StructuredReasons StructuredReasons { get; set; }
}

public class StructuredReasons
{
    public Reference Ref { get; set; }
}

public class Reference
{
    public string Ref { get; set; }
}

我遇到的问题是注册映射以获取映射的引用。当我需要映射到内部对象和父对象时,如何将 mappig 注册到仅包含对象的对象?

最佳答案

[为了清楚起见,我将把您的 Person POCO 称为 PersonDTO,因为第 3 方代码也有一个名为 Person 的类。]

有几种方法可以做到这一点。我过去使用过的一种方法是设置从 PersonDTONames 的映射,另一种是从 PersonDTOAddress 的映射,另一个从 PersonDTOReasons。最后,添加从 PersonDTOPerson 的映射。它看起来像这样(我省略了原因,但你明白了):

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<PersonDTO, Names>()
        .ForMember(d => d.Fullname, o => o.MapFrom(s => s.FullName));
    cfg.CreateMap<PersonDTO, Address>()            
        .ForMember(d => d.AddressLine,
                o => o.MapFrom(s => new[] { s.AddressLine1, s.AddressLine2 }));
    cfg.CreateMap<PersonDTO, Person>()
        .ForMember(d => d.Names, o => o.MapFrom(s => s))
        .ForMember(d => d.Address, o => o.MapFrom(s => s));
});
var mapper = config.CreateMapper();

var myPerson = new PersonDTO() { 
    FirstName = "Bob", 
    LastName = "Gold",
    AddressLine1 = "123 Main Street", 
    AddressLine2 = "Apt. 2"
};

var theirPerson = mapper.Map<Person>(myPerson);

但是 AutoMapper 的最新版本添加了一个 ForPath() 方法,该方法允许您访问内部对象,从而使所有这些变得更简单。现在代码折叠为:

var config = new MapperConfiguration(cfg => 
    cfg.CreateMap<PersonDTO, Person>()
        .ForPath(d => d.Names.Fullname, o => o.MapFrom(s => s.FullName))
        .ForPath(d => d.Address.AddressLine, 
                o => o.MapFrom(s => new[]  { s.AddressLine1, s.AddressLine2 }))
);
var mapper = config.CreateMapper();

编辑:我遗漏了一个可能会改变这两种方法之间平衡的方面。在第一种方法中,定义了多个映射,您可以免费获得具有匹配名称的任何字段。例如,您不需要显式地将 PesronDTO.City 映射到 Address.City(并且如果您更改 PersonDTO.FullName 上的大小写)成为 PersonDTO.Fullname,您也可以免费获得)。但在第二种方法中,即使名称匹配,您也必须显式映射所有嵌套字段。就您而言,我认为第一种方法可能更适合您,因为您只需显式映射 3 个字段,并且可以免费获得其他 4 个字段。对于第二种方法,您必须对所有 7 个字段执行 ForPath()

关于c# - 如何使用自动映射器将简单的 poco 映射到复杂的对象层次结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49152317/

相关文章:

c# - 如何在 DateTime 用户设置中包含毫秒?

c# - 抛出异常 C# 进阶

c# - 如果遇到不止一次,使自动映射器缓存对象

c# - 如何使用 AutoMapper 动态映射内部类型

c# - 绑定(bind)ListView不绑定(bind)

c# - 在 .NET Standard 上实现异步返回类型

c# - 无法使用 for 循环通过用户输入用 double 值填充数组。 C#

c# - 如何为 AutoMapper 实现自定义命名解析器

c# - Automapper - 当源对象具有带值的属性时不映射

c# - AutoMapper - 如何选择不执行 "inner"映射?