首页 > 解决方案 > 使用自动映射器按惯例展开

问题描述

在我的项目中,我尝试使用 automapper 尽可能按照约定将我的命令对象展开为我的域对象。
当我在映射配置文件中显式映射两个成员时,它可以工作,但根据 automapper 文档,我认为这也应该按惯例工作。我创建了一个 dotnetfiddle来演示最小的情况。

相关问题最终会导致人们明确添加映射,但这与 Automapper 的构建目的和文档相矛盾,不是吗?它也不适用于展平,所以我认为反向图是一个红鲱鱼。

映射

public class Mapping: Profile
{
    public Mapping()
    {
        this.CreateMap<CreateSelectionCommand, Selection>();
        // .ForMember(selection => selection.Name, opt => opt.MapFrom(x => x.SelectionName))
        .reverseMap()
    }
}

我期望的工作

[Fact]
public void ShouldMapName()
{
    var cmd = new CreateSelectionCommand {SelectionName = "selectionName"};
    var selection = _mapper.Map<Selection>(cmd);

    Assert.Equal(cmd.SelectionName, selection.Name); <== selection.Name == ""
}

上下文类

public class Selection
{
    public string Name { get; set; }
}

public class CreateSelectionCommand
{
    public string SelectionName { get; set; }
}

我是误读了文档还是遗漏了什么?

标签: c#automapper-10

解决方案


展平是关于将嵌套的“复杂”对象映射到“更高”级别的属性,即在您的情况下,如果CreateSelectionCommand具有Selection类型的属性,该Name属性将SelectionName在目标类型中映射到该属性(参见this fiddle)。

您可以尝试通过添加以下内容来使用前缀:

cfg.RecognizePrefixes("Selection");

到您的配置(请参阅this fiddle),但我怀疑它是否适合基于约定的处理。

此外,您似乎可以使用ISourceToDestinationNameMapperand添加自定义名称约定AddMemberConfiguration

class TypeNamePrefixedSourceToDestinationNameMapper : ISourceToDestinationNameMapper
{
    public MemberInfo GetMatchingMemberInfo(IGetTypeInfoMembers getTypeInfoMembers, TypeDetails typeInfo,
        Type destType,
        Type destMemberType, string nameToSearch)
    {
        return getTypeInfoMembers.GetMemberInfos(typeInfo)
            .FirstOrDefault(mi => mi.Name == destType.Name + nameToSearch);
    }
}

var config = new MapperConfiguration(cfg =>
{
    cfg.AddMemberConfiguration().AddName<TypeNamePrefixedSourceToDestinationNameMapper>();

    // ...
}

至少它适用于这种简单的情况,请参阅this fiddle


推荐阅读