.net AutoMapper CreateMap MemberList.None选项仍尝试绑定目标属性

rqdpfwrv  于 2023-03-13  发布在  .NET
关注(0)|答案(1)|浏览(211)

我定义了如下Map。在将DB实体复制到Map中使用MemberList.None的DTO时,Automapper仍然尝试Map名为StaffProperties的目标属性。它不应该使用显式Map并忽略目标对象中的其他属性吗?
自动Map器版本:12.0.1

标测

CreateMap<Staff, StaffDetailDto>()
        .ForMember(dest => dest.StaffProperties, opt => opt.MapFrom(src => JsonConvert.DeserializeObject<StaffProperties>(src.Properties)));

    CreateMap<StaffRole, StaffDetailDto>(MemberList.None)
        .ForMember(dest => dest.OrganizationRole, opt => opt.MapFrom((src, dest) =>
        {
            return (src != null) ? src.OrganizationRole : (OrganizationRole?)null;
        }));

服务层

var staffDetailDto = _mapper.Map<StaffDetailDto>(stf);

    // fetch staffRole from db

    staffDetailDto = _mapper.Map(staffRole, staffDetailDto);

在_mapper.Map(人员角色,人员详细信息Dto)上引发异常

Error mapping types.

Mapping types:
StaffRole -> StaffDetailDto
Baseline.Models.StaffRole -> Baseline.Services.Models.Staff.StaffDetailDto

Type Map configuration:
StaffRole -> StaffDetailDto
Baseline.Models.StaffRole -> Baseline.Services.Models.Staff.StaffDetailDto

Destination Member:
StaffProperties
j0pj023g

j0pj023g1#

我最终避免了MemberList.None,并创建了一个扩展方法IgnoreAllNonExisting()作为ForAllOtherMembers()的替代方法。注意,这并不理想,因为它依赖于AutoMapper内部,但满足了我的需要。

public static class AutoMapperExtensions
{
    public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>
    (this IMappingExpression<TSource, TDestination> expression)
    {
        // This is not an ideal way to depend on internals of AutoMapper to find existing mapping to ignore the rest.
        //  Given the breaking change of AutoMapper since 11.0 and the amount of dependency we have on IgnoreAllNonExisting method
        // I chose to go with this approach. Longer term we may need to move to explicit mapping
        // using a type converter for each of IgnoreAllNonExisting() dependency
        var propInfo = expression
                        .GetType()
                        .GetProperty(
                            "MemberConfigurations",
                            BindingFlags.Instance | BindingFlags.NonPublic);

        var explicitMappings = (List<IPropertyMapConfiguration>)propInfo.GetValue(expression, null);

        var flags = BindingFlags.Public | BindingFlags.Instance;
        var destinationProperties = typeof(TDestination).GetProperties(flags);

        foreach (var property in destinationProperties)
        {
            if (explicitMappings != null && explicitMappings.Any(r => string.Compare(r.DestinationMember.Name, property.Name) == 0))
                continue;

            expression.ForMember(property.Name, opt => opt.Ignore());
        }

        return expression;
    }
}

相关问题