如何在 Automapper 中从源代码进行局部映射

How to do a partial map from source in Automapper

我试图将对象的 4 个属性中的 2 个映射到目标类型。在我的例子中 DeletedByDeletedDate,其中 DeletedDate 将简单地设置为当前的 UTC 日期。

public class DeleteCommand : IRequest
{
    public string CodePath { get; set; }

    [JsonIgnore]
    public Guid? DeletedBy { get; set; }

    [IgnoreMap]
    public DeleteMode DeleteMode { get; set; } = DeleteMode.Soft;
}

这是我当前的配置:

CreateMap<DeleteCommand, Asset>(MemberList.Source)
    .ForMember(x => x.DeletedDate, opt => opt.MapFrom(src => DateTime.UtcNow))
    .ForMember(x => x.DeletedBy, opt => opt.MapFrom(src => src.DeletedBy));

运行 针对此特定映射器配置的单元测试给出了 2 个缺少映射的错误:

[Fact]
public void MapperConfigShouldBeValid()
{
    _config.AssertConfigurationIsValid();
}

Unmapped properties: DeletedDate DeleteMode

这让我很困惑,因为 Date 是明确定义的,并且 DeleteMode 设置为默认忽略。如果可能的话,我想避免创建另一个 dto 从第一个 dto 映射到实体,通过设置审计字段来软删除。

到目前为止我尝试过的事情:

删除 DeletedDate 作为 属性 解决了我 50% 的问题,因为我在源代码中不再需要它。

另一个正在用 ForSourceMember(x => x.DeleteMode, y => x.DoNotValidate())

更新地图

这也适用于快速单元测试:

[Fact]
public void DeleteMapShouldSetAuditFields()
{
    var asset = new Asset();
    var cmd = new DeleteCommand
    {
        DeletedBy = Guid.NewGuid()
    };

    _mapper.Map(cmd, asset);

    Assert.NotNull(asset.DeletedBy);
    Assert.NotNull(asset.DeletedDate);
    Assert.Equal(cmd.DeletedBy, asset.DeletedBy);
}

这可以通过从 CreateMap() 的参数列表中删除 MemberList.Source 并忽略所有剩余的未映射目标成员来解决。

CreateMap<DeleteCommand, Asset>()
.ForMember(x => x.DeletedDate, opt => opt.MapFrom(src => DateTime.UtcNow))
.ForMember(x => x.DeletedBy, opt => opt.MapFrom(src => src.DeletedBy))
.ForAllOtherMembers(x => x.Ignore())

同样可以通过 CreateMap(MemberList.None) 来实现。这甚至不需要明确忽略所有其他目标成员。