我有一个简单的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注册到只包含对象的对象?
答案 0 :(得分:4)
[为了清楚起见,我将打电话给你的人员POCO PersonDTO
,因为第三方代码也有一个名为Person
的课程。]
有几种方法可以做到这一点。我过去使用过的一种方法,包括设置从PersonDTO
到Names
的映射,另一个从PersonDTO
到Address
,另一个来自PersonDTO
到Reasons
。最后,添加从PersonDTO
到Person
的映射。它看起来像这样(我遗漏了Reasons
,但你明白了):
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
,您就可以免费获得该ForPath()
以及)。但在第二种方法中,即使名称匹配,也必须显式映射所有嵌套字段。在你的情况下,我认为第一种方法可能对你更好,因为你必须只显示3个字段,并免费获得其他4个字段。对于第二种方法,您必须为所有7个字段执行package com.example.hodor.stringcut;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private EditText textView, textView1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (EditText) findViewById(R.id.editText);
textView1 = (EditText) findViewById(R.id.editText1);
ArrayList<String> listDate = new ArrayList<>();
ArrayList<String> listDate1 = new ArrayList<>();
listDate.add("10 - 07 - 2017 - 12:32:45");
listDate.add("10 - 07 - 2017 - 12:35:45");
listDate.add("10 - 07 - 2017 - 12:36:45");
listDate.add("10 - 07 - 2017 - 12:38:45");
listDate.add("10 - 07 - 2017 - 12:30:45");
textView.setText(listDate.get(1));
for (int i = 0; i < listDate.size(); i++) {
String date = listDate.get(i);
listDate1.add(date.substring(0, date.length() -11));
}
textView.setText(listDate1.get(1));
}
}
。
答案 1 :(得分:0)
默认情况下,它会尝试将SourceType的属性与DestinationType的属性进行匹配。但是对于您的场景,您将使用ForMember扩展方法添加一些规范,如下所示:
Mapper.CreateMap<Foo, FooDTO>()
.ForMember(e => e.Bars, o => o.ExplicitExpansion());
这里有一个现有的帖子: AutoMapper define mapping level