首页 > 解决方案 > Automapper:UseDestinationValue 不适用于集合?

问题描述

假设有类:

public class Foo
{
    public List<Bar> Bars { get; set; }
}

public class Bar
{
    public string Name { get; set; }
    public string Description { get; set; }
}

public class FooDto
{
    public List<BarDto> Bars { get; set; }
}

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

public class MapperProfile : Profile
{
    public MapperProfile()
    {
        CreateMap<FooDto, Foo>();
        CreateMap<BarDto, Bar>()
            .ForMember(dest => dest.Description, opt => opt.UseDestinationValue());
    }
}

如果我使用一对一映射,一切都按预期工作:

var mapper = new Mapper(new MapperConfiguration(e => e.AddProfile(typeof(MapperProfile))));

var bar = new Bar
{
    Name = "name",
    Description = "description"
};

var barDto = new BarDto
{
    Name = "updated name"
};

mapper.Map(barDto, bar);

Console.WriteLine(bar.Name);
Console.WriteLine(bar.Description);

// Output:
// updated name
// description

但这不适用于收藏:

var mapper = new Mapper(new MapperConfiguration(e => e.AddProfile(typeof(MapperProfile))));

var foo = new Foo
{
    Bars = new List<Bar>
    {
        new Bar
        {
            Name = "name",
            Description = "description",
        }
    }
};

var fooDto = new FooDto
{
    Bars = new List<BarDto>
    {
        new BarDto
        {
            Name = "updated name"
        }
    }
};

mapper.Map(fooDto, foo);

foreach (var bar in foo.Bars)
{
    Console.WriteLine(bar.Name);
    Console.WriteLine(bar.Description);
}

// Output:
// updated name
//                

映射后BarDescription为空(已测试9.0.010.0.0版本)。

是什么原因,如何解决?

标签: c#.netautomapper

解决方案


最后,我找到了解决方案。Automapper 在映射之前清除目标集合,这就是所有属性都设置为默认值的原因。 AutoMapper.Collection在这种情况下可以提供帮助。

public class Foo
{
    public List<Bar> Bars { get; set; }
}

public class Bar
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

public class FooDto
{
    public List<BarDto> Bars { get; set; }
}

public class BarDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class MapperProfile : Profile
{
    public MapperProfile()
    {
        CreateMap<FooDto, Foo>();
        CreateMap<BarDto, Bar>()
            .EqualityComparison((src, dest) => src.Id == dest.Id);
    }
}


并像这样使用:

var mapper = new Mapper(new MapperConfiguration(e =>
{
    e.AddCollectionMappers();
    e.AddProfile(typeof(MapperProfile));
}));

var foo = new Foo
{
    Bars = new List<Bar>
    {
        new Bar
        {
            Id = 1,
            Name = "name",
            Description = "description",
        }
    }
};

var fooDto = new FooDto
{
    Bars = new List<BarDto>
    {
        new BarDto
        {
            Id = 1,
            Name = "updated name"
        }
    }
};

mapper.Map(fooDto, foo);

foreach (var bar in foo.Bars)
{
    Console.WriteLine(bar.Name);
    Console.WriteLine(bar.Description);
}

// Output:
// updated name
// description

推荐阅读