Map complex type to flat type in AutoMapper
I have a complex object like:
public class BusinessUnit
{
public TradingDesk TradingDesk { get; }
public string Division { get; }
public BusinessUnit(string division, TradingDesk tradingDesk)
{
Division = division;
TradingDesk = tradingDesk;
}
}
I want to map this to the flat type:
public class Row
{
//TradingDesk properties
public string TraderFirstName { get; set; }
public string TraderLastName { get; set; }
public string TradingDeskName { get; set; }
public string Division { get; set; }
}
I have already configured AutoMapper
for TradingDesk
:
CreateMap<TradingDesk, Row>().ForMember(vm => vm.TradingDeskName, op => op.MapFrom(src => src.Name));
so the following test is passing:
[Test]
public void Should_Map_TradingDesk_To_Row()
{
var tradingDesk = Fixture.Create<TradingDesk>();
var mapped = AutoMapper.Map<Row>(tradingDesk);
mapped.TradingDeskName.Should()
.Be(tradingDesk.Name);
mapped.TraderFirstName.Should()
.Be(tradingDesk.Trader.FirstName);
mapped.TraderLastName.Should()
.Be(tradingDesk.Trader.LastName);
}
But when I try to map BusinessUnit
to Row
I am having to reconfigure AutoMapper
for TradingDesk
as such:
CreateMap<BusinessUnit, Row>()
.ForMember(vm => vm.TradingDeskName, op => op.MapFrom(src => src.TradingDesk.Name))
.ForMember(vm => vm.TraderFirstName, op => op.MapFrom(src => src.TradingDesk.Trader.FirstName))
.ForMember(vm => vm.TraderLastName, op => op.MapFrom(src => src.TradingDesk.Trader.LastName));
I expect that AutoMapper
should use the already configured source & destination type mapping when it needs to map TradingDesk
to Row
while mapping BusinessUnit
. This way I can build the configuration from the smallest to the largest type while flattening out a complex object without having to define mapping for each individual member in the flattened type.
实际的语法可能会有所不同,因为我以静态的方式使用AutoMapper,但原理保持不变:
Mapper.CreateMap<BusinessUnit, Row>()
.ConvertUsing(source => Mapper.Map<TradingDesk, Row>(source.TradingDesk));
First of I think your map for trading desk would be just
CreateMap<TradingDesk, Row>();
If memory serves me right, since your destination member matches source member name when ".' are removed then you do not need to specify it explicitly.
If you change your Row class to this
public class Row
{
//TradingDesk properties
public string TradingDeskTraderFirstName { get; set; }
public string TradingDeskTraderLastName { get; set; }
public string TradingDeskName { get; set; }
public string Division { get; set; }
}
your map would be
CreateMap<BusinessUnit, Row>();
If you are never going to map to TradingDesk, then remove that map.
If this is defined in some Profile, you can also say
RecognizePrefixes("TradingDesk");
and then you do not need to change your Row class.
If you do not want to create a special converters or property resolvers you can perform the second mapping after the map of the main object, eg:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<TradingDesk, Row>()
.ForMember(vm => vm.TradingDeskName, op => op.MapFrom(src => src.Name));
cfg.CreateMap<BusinessUnit, Row>()
.AfterMap((businessUnit, row) => { Mapper.Map(businessUnit.TradingDesk, row); });
});
var source = new BusinessUnit("division", new TradingDesk { TraderFirstName = "FirstName", TraderLastName = "LastName", Name = "DeskName" });
var dest = Mapper.Map<Row>(source);
In this case, the object has been mapped without creating a new instance.
链接地址: http://www.djcxy.com/p/6382.html