首页
/ Mapperly映射库中如何实现复杂属性转换逻辑

Mapperly映射库中如何实现复杂属性转换逻辑

2025-06-24 21:19:42作者:何举烈Damon

在对象映射场景中,我们经常遇到需要基于多个源属性计算目标属性值的需求。本文以Mapperly映射库为例,探讨几种实现复杂属性转换的方法。

常见需求场景

假设我们有一个汽车类Car需要映射到DTO类CarDto,其中价格字段需要特殊处理:不仅需要转换价格单位,还需要考虑加价(markup)因素。

方法一:使用MapProperty.Use

Mapperly提供了MapProperty特性,允许为特定属性指定自定义映射方法:

[MapProperty(nameof(Car.Price), nameof(CarDto.Price), Use = nameof(MapPrice))]
public partial CarDto MapCar(Car source);

[UserMapping(Default = false)]
private string MapPrice(decimal price)
    => (price / 100).ToString("C");

但这种方法只能访问单个属性值,无法满足需要多个属性参与计算的场景。

方法二:结合BeforeMap/AfterMap

更灵活的方式是使用BeforeMap或AfterMap钩子:

[Mapper]
public partial class CarMapper
{
    public partial CarDto MapCar(Car source);
    
    [BeforeMap]
    private void BeforeMap(Car source, CarDto target)
    {
        target.Price = (source.Price + source.Markup / 100).ToString("C");
    }
}

这种方法可以访问源对象的所有属性,实现复杂的转换逻辑。

方法三:忽略属性+手动映射

另一种模式是先忽略目标属性,然后在映射方法中手动处理:

[Mapper]
public partial class CarMapper
{
    [MapProperty(nameof(Car.Price), Ignore = true)]
    public partial CarDto MapCar(Car source);
    
    public CarDto MapCarWithPrice(Car source)
    {
        var dto = MapCar(source);
        dto.Price = CalculatePrice(source);
        return dto;
    }
    
    private string CalculatePrice(Car car)
    {
        return (car.Price + car.Markup / 100).ToString("C");
    }
}

最佳实践建议

  1. 对于简单属性转换,优先使用MapProperty.Use
  2. 需要多个属性参与计算时,使用BeforeMap/AfterMap
  3. 特别复杂的转换逻辑可考虑拆分到单独方法中
  4. 保持映射逻辑的单一职责,避免过于复杂的转换

Mapperly作为高性能的编译时映射解决方案,虽然不像AutoMapper那样支持直接在属性映射中访问完整对象,但通过上述模式同样可以实现各种复杂映射需求,同时保持优异的性能表现。

登录后查看全文
热门项目推荐