简体   繁体   中英

How to do a partial map from source in Automapper

I am trying to map only 2 out of 4 properties from an object to the destination type. In my case DeletedBy and DeletedDate , where as DeletedDate will simply be set to the current UTC date.

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

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

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

This is my current configuration:

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));

Running a unit test against this specific mapper configuration gives me 2 errors for a missing mapping:

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

Unmapped properties: DeletedDate DeleteMode

This is confusing me, since the Date is explicitly defined and the DeleteMode is set to be ignored by default. If possible I want to avoid to create another dto to be mapped from a first dto and then to the entity, to be soft-deleted, by setting the audit fields.

Things I've tried so far:

  • IgnoreMapAttribute as shown above
  • ForSourceMember() , seems to not support an Ignore method for a source property.

Removing DeletedDate as a property solved 50% of my issues, since I don't need it on the source any more.

The other one was updating the map with ForSourceMember(x => x.DeleteMode, y => x.DoNotValidate())

This then also works in a quick unit test:

[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);
}

This can be solved by removing MemberList.Source from argument list of CreateMap() and ignoring all remaining unmapped destination members.

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())

Same could be achieved by having CreateMap(MemberList.None) . This doesn't even require explicitly ignoring all other destination members.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM