假设我有两个模型类:
public class People {
public string FirstName {get;set;}
public string LastName {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
还有一类电话:
public class Phone {
public string Number {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
我想转换为PeoplePhoneDto,如下所示:
public class PeoplePhoneDto {
public string FirstName {get;set;}
public string LastName {get;set;}
public string PhoneNumber {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
让我们在我的控制器中说:
var people = repository.GetPeople(1);
var phone = repository.GetPhone(4);
// normally, without automapper I would made
return new PeoplePhoneDto(people, phone) ;
Run Code Online (Sandbox Code Playgroud)
我似乎找不到这个场景的任何例子.这可能吗 ?
注意:示例不是真实的,仅针对此问题.
Ser*_*kiy 90
您无法直接将多个来源映射到单个目的地 - 您应该逐个应用地图,如Andrew Whitaker的回答所述.因此,您必须定义所有映射:
Mapper.CreateMap<People, PeoplePhoneDto>();
Mapper.CreateMap<Phone, PeoplePhoneDto>()
.ForMember(d => d.PhoneNumber, a => a.MapFrom(s => s.Number));
Run Code Online (Sandbox Code Playgroud)
然后通过任何这些映射创建目标对象,并将其他映射应用于创建的对象.这个步骤可以通过非常简单的扩展方法简化:
public static TDestination Map<TSource, TDestination>(
this TDestination destination, TSource source)
{
return Mapper.Map(source, destination);
}
Run Code Online (Sandbox Code Playgroud)
用法很简单:
var dto = Mapper.Map<PeoplePhoneDto>(people)
.Map(phone);
Run Code Online (Sandbox Code Playgroud)
Lui*_*eia 29
如果您使用的是 C# 7+,请尝试此操作(@Pawe\xc5\x82 Bejgerthat 的答案略有不同,这将使事情变得更加简单):
\nMapper.CreateMap<(People people, Phone phone), PeoplePhoneDto>()\n .ForMember(d => d.FirstName, opt => opt.MapFrom(s => s.people.FirstName))\n .ForMember(d => d.LastName, opt => opt.MapFrom(s => s.people.LastName))\n .ForMember(d => d.Number, opt => opt.MapFrom(s => s.phone.Number ));\nRun Code Online (Sandbox Code Playgroud)\n然后像这样使用它:
\nvar peoplePhoneDto = EntityMapper.Map<PeoplePhoneDto>((people, phone));\nRun Code Online (Sandbox Code Playgroud)\n是的,你需要在参数周围加上几个括号,这不是一个错误。其背后的原因是您传递的是一个(而不是两个)单个源,而该源恰好是一个(人员,电话)元组。
\nPaw*_*ger 17
你可以使用一个Tuple:
Mapper.CreateMap<Tuple<People, Phone>, PeoplePhoneDto>()
.ForMember(d => d.FirstName, opt => opt.MapFrom(s => s.Item1.FirstName))
.ForMember(d => d.LastName, opt => opt.MapFrom(s => s.Item1.LastName))
.ForMember(d => d.Number, opt => opt.MapFrom(s => s.Item2.Number ));
Run Code Online (Sandbox Code Playgroud)
如果您有更多的源模型,您可以使用不同的表示(列表,字典或其他),将所有这些模型作为源集合在一起.
上面的代码应该优先放在一些AutoMapperConfiguration文件中,设置一次并全局,然后在适用时使用.
默认情况下,AutoMapper仅支持单个数据源.所以不可能直接设置多个源(没有将它包装在一个集合中),因为那么如果两个源模型具有相同名称的属性,我们怎么知道呢?
虽然有一些解决方法可以实现这一目标:
public static class EntityMapper
{
public static T Map<T>(params object[] sources) where T : class
{
if (!sources.Any())
{
return default(T);
}
var initialSource = sources[0];
var mappingResult = Map<T>(initialSource);
// Now map the remaining source objects
if (sources.Count() > 1)
{
Map(mappingResult, sources.Skip(1).ToArray());
}
return mappingResult;
}
private static void Map(object destination, params object[] sources)
{
if (!sources.Any())
{
return;
}
var destinationType = destination.GetType();
foreach (var source in sources)
{
var sourceType = source.GetType();
Mapper.Map(source, destination, sourceType, destinationType);
}
}
private static T Map<T>(object source) where T : class
{
var destinationType = typeof(T);
var sourceType = source.GetType();
var mappingResult = Mapper.Map(source, sourceType, destinationType);
return mappingResult as T;
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
var peoplePhoneDto = EntityMapper.Map<PeoplePhoneDto>(people, phone);
Run Code Online (Sandbox Code Playgroud)
但说实话,即使我已经使用AutoMapper几年了,我也从未需要使用来自多个来源的映射.例如,当我在单视图模型中需要多个业务模型时,我只是将这些模型嵌入到视图模型类中.
所以在你的情况下,它看起来像这样:
public class PeoplePhoneDto {
public People People { get; set; }
public Phone Phone { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我会编写一个扩展方法,如下所示:
public static TDestination Map<TSource1, TSource2, TDestination>(
this IMapper mapper, TSource1 source1, TSource2 source2)
{
var destination = mapper.Map<TSource1, TDestination>(source1);
return mapper.Map(source2, destination);
}
Run Code Online (Sandbox Code Playgroud)
那么用法将是:
mapper.Map<People, Phone, PeoplePhoneDto>(people, phone);
Run Code Online (Sandbox Code Playgroud)