在将包含抽象属性的容器类映射到我的View Model目标类时遇到一些问题。
映射源类
//Container class
public class giftcardDetailResponse : Response
{
//Instance of either UsergiftcardDTO or ImportedgiftcardDTO
public giftcardInstanceDTO Usergiftcard { get; set; }
}
public abstract class giftcardInstanceDTO : BaseDTO
{
public int UserId { get; set; }
public decimal Balance { get; set; }
public string BarcodeValue { get; set; }
public string BarcodeUrl { get; set; }
public string Code { get; set; }
public string Pin { get; set; }
public bool RefreshBalanceSupported { get; set; }
public bool Viewed { get; set; }
public bool IsArchived { get; set; }
public virtual UserDTO User { get; set; }
}
public class UsergiftcardDTO : giftcardInstanceDTO
{
public int giftcardId { get; set; }
public DateTimeOffset? activatedAt { get; set; }
public DateTimeOffset? BalanceUpdatedAt { get; set; }
public string ClaimUrl { get; set; }
public string ClaimSecret { get; set; }
public PrivacySettings Privacy { get; set; }
public bool IsPending { get; set; }
public bool BoughtAsgift { get; set; }
public virtual giftcardDTO giftcard { get; set; }
}
public class ImportedgiftcardDTO : giftcardInstanceDTO
{
public string RetailerName { get; set; }
public string FrontImage { get; set; }
public string BackImage { get; set; }
}
映射目标类别
//Front-end view model
public class giftcardDetailViewModel
{
public int Id { get; set; }
public string RetailerName { get; set; }
public decimal Amount { get; set; }
public string Image { get; set; }
}
映射配置
CreateMap<giftcardDetailResponse,giftcardDetailViewModel>()
.IncludeMembers(src => src.Usergiftcard);
//Automapper should pick a concrete mapping for this
CreateMap<giftcardInstanceDTO,giftcardDetailViewModel>()
.IncludeAllDerived();
//Concrete mappings to View Model
CreateMap<UsergiftcardDTO,giftcardDetailViewModel>()
.ForMember(dest => dest.Id,opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.Image,opt => opt.MapFrom(src => src.giftcard.Image))
.ForMember(dest => dest.Amount,opt => opt.MapFrom(src => src.Balance))
.ForMember(dest => dest.RetailerName,opt => opt.MapFrom(src => src.giftcard.Merchant.Name));
CreateMap<ImportedgiftcardDTO,opt => opt.MapFrom(src => src.FrontImage))
.ForMember(dest => dest.Amount,opt => opt.MapFrom(src => src.RetailerName));
问题在于,当我将giftcardDetailResponse
映射到giftcardDetailViewModel
时,Automapper没有为抽象属性的派生类选择显式映射。例如,如果我的代码看起来像这样
var containerClass = new giftcardDetailResponse();
containerClass.Usergiftcard = new ImportedgiftcardDTO();
var viewModel = MapperWrapper.Mapper.Map<giftcardDetailViewModel>(containerClass);
执行树看起来像这样
//Automapper generated execution plan
(src,dest,ctxt) =>
{
giftcardDetailViewModel typeMapDestination;
return (src == null)
? null
: {
typeMapDestination = dest ?? new giftcardDetailViewModel();
try
{
var resolvedValue = ((src == null) || ((src.Usergiftcard == null) || false)) ? default(int) : src.Usergiftcard.Id;
typeMapDestination.Id = resolvedValue;
}
catch (Exception ex)
{
throw new AutoMapperMappingException(
"Error mapping types.",ex,AutoMapper.TypePair,TypeMap,PropertyMap);
return default(int);
}
return typeMapDestination;
};
}
似乎只选择在giftcardInstanceDTO
和giftcardDetailViewModel
中具有相同名称的属性,而不使用我定义的映射。
但是,当我仅将抽象属性显式映射到我的视图模型(例如
)时,我正在寻找的东西与执行树类似。var propertyModel = MapperWrapper.Mapper.Map<giftcardDetailViewModel>(containerClass.Usergiftcard);
正确显示了我的派生映射
//Automapper generated execution plan
(src,ctxt) =>
{
giftcardDetailViewModel typeMapDestination;
return (src == null)
? null
: {
typeMapDestination = dest ?? new giftcardDetailViewModel();
try
{
var resolvedValue =
{
try
{
return ((src == null) || false) ? default(int) : src.Id;
}
catch (NullReferenceException)
{
return default(int);
}
catch (ArgumentNullException)
{
return default(int);
}
};
typeMapDestination.Id = resolvedValue;
}
catch (Exception ex)
{
throw new AutoMapperMappingException(
"Error mapping types.",PropertyMap);
return default(int);
}
try
{
var resolvedValue =
{
try
{
return ((src == null) || false) ? null : src.RetailerName;
}
catch (NullReferenceException)
{
return null;
}
catch (ArgumentNullException)
{
return null;
}
};
var propertyValue = (resolvedValue == null) ? null : resolvedValue;
typeMapDestination.RetailerName = propertyValue;
}
catch (Exception ex)
{
throw new AutoMapperMappingException(
"Error mapping types.",PropertyMap);
return null;
}
try
{
var resolvedValue =
{
try
{
return ((src == null) || false) ? null : src.FrontImage;
}
catch (NullReferenceException)
{
return null;
}
catch (ArgumentNullException)
{
return null;
}
};
var propertyValue = (resolvedValue == null) ? null : resolvedValue;
typeMapDestination.Image = propertyValue;
}
catch (Exception ex)
{
throw new AutoMapperMappingException(
"Error mapping types.",PropertyMap);
return null;
}
try
{
var resolvedValue =
{
try
{
return ((src == null) || false) ? default(decimal) : src.Balance;
}
catch (NullReferenceException)
{
return default(decimal);
}
catch (ArgumentNullException)
{
return default(decimal);
}
};
typeMapDestination.Amount = resolvedValue;
}
catch (Exception ex)
{
throw new AutoMapperMappingException(
"Error mapping types.",PropertyMap);
return default(decimal);
}
return typeMapDestination;
};
}
文档说,如果已经定义了映射,则可以使用IncludeMembers
将子对象展平到目标对象。但是,当子对象是抽象对象时,此行为在这种情况下似乎无法正常工作。