问题
I have a bunch of DTO classes that inherit from this CardBase
:
// base class
public class CardBase
{
public int TransId {get; set; }
public string UserId { get; set; }
public int Shift { get; set; }
}
// one of the concrete classes
public class SetNewCardSettings : CardBase
{
// specific properties ...
}
In my MVC project I have a bunch of view models with a AuditVm
complex type that has the same properties of CardBase
:
public class AuditVm
{
public int TransId {get; set; }
public string UserId { get; set; }
public int Shift { get; set; }
}
public class CreateCardVm : CardVm
{
// specific properties here ...
public AuditVm Audit { get; set }
}
Those view models cannot inherit from AuditVm
because each of them already has a parent. I thought I could setup my mapping like below so I would not have to specify the map from AuditVm
to the CardBase
for every view model that has AuditVm
as a complex type. But it is not working. How do I properly map from a complex type to a flatten type with properties on the base class?
Mapper.CreateMap<AuditorVm, CardBase>()
.Include<AuditorVm, SetNewCardSettings>();
// this does not work because it ignores my properties that I map in the second mapping
// if I delete the ignore it says my config is not valid
Mapper.CreateMap<AuditorVm, SetNewCardSettings>()
.ForMember(dest => dest.Temp, opt => opt.Ignore())
.ForMember(dest => dest.Time, opt => opt.Ignore());
Mapper.CreateMap<CreateCardVm, SetNewCardSettings>()
// this gives me an error
.ForMember(dest => dest, opt => opt.MapFrom(src => Mapper.Map<AuditorVm, SetNewCardSettings>(src.Auditor)));
// I also tried this and it works, but it does not map my specific properties on SetNewCardSettings
//.ConvertUsing(dest => Mapper.Map<AuditorVm, SetNewCardSettings>(dest.Auditor));
UPDATE: here is the fiddle https://dotnetfiddle.net/iccpE0
回答1:
.Include
is for a very specific case--you have two identically-structured class hierarchies you'd like to map, for example:
public class AEntity : Entity { }
public class BEntity : Entity { }
public class AViewModel : ViewModel { }
public class BViewModel : ViewModel { }
Mapper.CreateMap<Entity, ViewModel>()
.Include<AEntity, AViewModel>()
.Include<BEntity, BViewModel>();
// Then map AEntity and BEntity as well.
So unless you have this kind of situation, .Include
isn't the right thing to use.
I think your best bet is to use ConstructUsing
:
Mapper.CreateMap<AuditVm, CardBase>();
Mapper.CreateMap<AuditVm, SetNewCardSettings>()
.ConstructUsing(src =>
{
SetNewCardSettings settings = new SetNewCardSettings();
Mapper.Map<AuditVm, CardBase>(src, settings);
return settings;
})
.IgnoreUnmappedProperties();
Mapper.CreateMap<CreateCardVm, SetNewCardSettings>()
.ConstructUsing(src => Mapper.Map<SetNewCardSettings>(src.Audit))
.IgnoreUnmappedProperties();
I've also incorporated this answer's extension method to ignore all unmapped properties. Since we're using ConstructUsing
, AutoMapper doesn't know that we've already taken care of those properties.
Updated fiddle: https://dotnetfiddle.net/6ZfZ3z
来源:https://stackoverflow.com/questions/27317719/automapper-how-to-not-repeat-mapping-config-from-complex-type-to-base-class