将具有抽象属性的类映射到目标 映射源类映射目标类别映射配置

在将包含抽象属性的容器类映射到我的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;
    };
}

似乎只选择在giftcardInstanceDTOgiftcardDetailViewModel中具有相同名称的属性,而不使用我定义的映射。

但是,当我仅将抽象属性显式映射到我的视图模型(例如

)时,我正在寻找的东西与执行树类似。
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将子对象展平到目标对象。但是,当子对象是抽象对象时,此行为在这种情况下似乎无法正常工作。

iCMS 回答:将具有抽象属性的类映射到目标 映射源类映射目标类别映射配置

const val CPR_TRANSFORMATION = "AES/CBC/PKCS7Padding" const val ALGORITHM_TYPE = "PBKDF2WithHmacSHA1" const val ITERATION_AMOUNT = 12000 const val KEY_SIZE = 256 private fun encrypt(passCode: String,data: ByteArray): Encrypted { //e.g.: passCode = "0000" val salt = ByteArray(256) SecureRandom().nextBytes(salt) val iv = ByteArray(16) SecureRandom().nextBytes(iv) val cipher = Cipher.getInstance(CPR_TRANSFORMATION) cipher.init(Cipher.ENCRYPT_MODE,getSecretKey(passCode,salt),IvParameterSpec(iv)) val raw = cipher.doFinal(data) return Encrypted(salt.encodeBase64(),iv.encodeBase64(),raw.encodeBase64()) } private fun getSecretKey(passCode: String,salt: ByteArray): Key { val pbKeySpec = PBEKeySpec(passCode.toCharArray(),salt,ITERATION_AMOUNT,KEY_SIZE) val keyBytes = SecretKeyFactory.getInstance(ALGORITHM_TYPE).generateSecret(pbKeySpec).encoded return SecretKeySpec(keyBytes,KeyProperties.KEY_ALGORITHM_AES) } 不会实现这种“动态”行为,但是您可以这样做:

IncludeMembers
本文链接:https://www.f2er.com/1790656.html

大家都在问