Jos*_*son 39 mapping automapper
我一直在尝试使用AutoMapper来节省从我的DTO到我的域对象的时间,但是我在配置地图时遇到了麻烦,以至于它工作正常,我开始怀疑AutoMapper是否可能是错误的工具工作.
考虑这个域对象的例子(一个实体和一个值):
public class Person
{
public string Name { get; set; }
public StreetAddress Address { get; set; }
}
public class StreetAddress
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的DTO(来自Linq-to-SQL对象)的出现大致如下:
public class PersonDTO
{
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在我的存储库中执行此操作:
return Mapper.Map<PersonDTO, Person>(result);
Run Code Online (Sandbox Code Playgroud)
我已经尝试过各种方式配置AutoMapper,但我不断得到通用的Missing类型映射配置或不支持的映射错误,没有详细信息告诉我我失败的地方.
我尝试了很多不同的配置,但这里有几个:
Mapper.CreateMap<PersonDTO, Person>()
.ForMember(dest => dest.Address, opt => opt.MapFrom(Mapper.Map<Person, Domain.StreetAddress>));
Run Code Online (Sandbox Code Playgroud)
和
Mapper.CreateMap<Person, Domain.Person>()
.ForMember(dest => dest.Address.Address1, opt => opt.MapFrom(src => src.Address))
.ForMember(dest => dest.Address.City, opt => opt.MapFrom(src => src.City))
.ForMember(dest => dest.Address.State, opt => opt.MapFrom(src => src.State));
Run Code Online (Sandbox Code Playgroud)
我读过,扁平化与AutoMapper对象很容易,但unflattening他们是不容易的......甚至是不可能的.任何人都可以告诉我,我是否正在尝试做不可能的事情,如果不是我做错了什么?
请注意,我的实际对象有点复杂,所以我可能会遗漏错误的关键信息...如果我正在做的事情看起来正确我可以提供更多信息或开始简化我的对象进行测试.
syd*_*yos 65
这似乎对我有用:
Mapper.CreateMap<PersonDto, Address>();
Mapper.CreateMap<PersonDto, Person>()
.ForMember(dest => dest.Address, opt => opt.MapFrom( src => src )));
Run Code Online (Sandbox Code Playgroud)
基本上,创建从dto到两个对象的映射,然后将其用作子对象的源.
无法发表评论,所以发帖回答.我想AutoMapper实现有一些变化,所以回答来自HansoS提出的/sf/answers/360802501/不再可编译.虽然还有另一种方法可以在这种情况下使用 - ResolveUsing
:
Mapper.CreateMap<Person, Domain.Person>()
.ForMember(dest => dest.Address, opt => opt.ResolveUsing( src => { return new Address() {Address1 = src.Address, City = src.City, State = src.State }; }))
Run Code Online (Sandbox Code Playgroud)
除了sydneyos的答案,根据Trevor de Koekkoek的评论,这种方式可以实现双向映射
public class Person
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
}
public class PersonViewModel
{
public string Name { get; set; }
public string AddressStreet { get; set; }
public string AddressCity { get; set; }
public string AddressState { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
自动映射
Mapper.Initialize(cfg => cfg.RecognizePrefixes("Address"));
Mapper.CreateMap<Person, PersonViewModel>();
Mapper.CreateMap<PersonViewModel, Address>();
Mapper.CreateMap<PersonViewModel, Person>()
.ForMember(dest => dest.Address, opt => opt.MapFrom( src => src )));
Run Code Online (Sandbox Code Playgroud)
如果实现NameOf类,则可以删除前缀魔术字符串
Mapper.Initialize(cfg => cfg.RecognizePrefixes(Nameof<Person>.Property(x => x.Address)));
Run Code Online (Sandbox Code Playgroud)
编辑:在C#6
Mapper.Initialize(cfg => cfg.RecognizePrefixes(nameof(Person.Address)));
Run Code Online (Sandbox Code Playgroud)
使用https://github.com/omuleanu/ValueInjecter,它压扁和unflattening,和其他任何你需要的,有一个在下载asp.net的MVC示例应用程序,所有的功能都证明(也单元测试)
小智 5
这可能会迟到但您可以通过使用lambda表达式来创建对象来解决这个问题:
Mapper.CreateMap<Person, Domain.Person>()
.ForMember(dest => dest.Address, opt => opt.MapFrom( src => { return new Address() {Address1 = src.Address, City = src.City, State = src.State }; }))
Run Code Online (Sandbox Code Playgroud)