繁体   English   中英

自动映射器和不变性

[英]Automapper and immutability

是否可以将 AutoMapper 与不可变类型一起使用?

例如我的域类型是不可变的,我想将我的视图类型映射到这个。

我相信它不是,但只是想确认这一点。

此外,由于域类型不可变是最佳实践,因此将视图类型映射到域类型时的最佳实践是什么?

我通常手动进行从视图类型到域类型的映射,因为我通常会通过更复杂的接口、使用方法等进行工作。 如果您使用 AutoMapper 从视图到域,您现在被锁定在一个贫血的域模型中,无论您是否有意决定。

假设您确实想要域类型的不可变属性,例如Id 您的域类型可能如下所示:

public class DomainType
{
    public DomainType(int id)
    {
        Id = id;
    }

    public int Id { get; }
    // other mutable properties
    // ...
}

然后,您可以使用您选择的公共构造函数来使用ConstructUsing ,例如:

CreateMap<ViewType, DomainType>()
    .ConstructUsing(vt => new DomainType(vt.Id));

然后以正常方式映射所有可变属性

AutoMapper 依赖属性设置器来完成它的工作,所以如果你有只读属性,AutoMapper 将没有多大用处。

您可以覆盖映射行为,例如,将其配置为调用特定的构造函数,但这基本上违背了 AutoMapper 的目的,因为那时您正在手动进行映射,并且您只能成功地在过程。

你的域模型是不可变的,这对我来说没有多大意义。 你如何更新它? 整个应用程序是只读的吗? 如果是这样,为什么您需要映射域模型而不是from 一个不可变的域模型听起来……很没用。

PS 我假设你的意思是这个 AutoMapper而不是Fluent NHibernate 中自动映射功能,甚至是其他一些完全不同的东西。 如果那是错误的,那么您应该更具体并为您的平台/语言添加标签。

我们有使用构建器模式的不可变对象。 映射它们需要更多的样板代码,但这是可能的

// ViewModel
public class CarModel : IVehicleModel 
{
    private CarModel (Builder builder)
    {
        LicensePlate = builder.LicensePlate;
    }    

    public string LicensePlate { get; }

    //
    public Builder
    {
        public string LicensePlate { get; set; }
    }
}


// Model
public class CarViewModel : IVehicleViewModel
{
    private CarViewModel (Builder builder)
    {
        LicensePlate = builder.LicensePlate ;
    }    

    public ILicensePlate LicensePlate { get; }

    //
    public Builder
    {
        public ILicensePlate LicensePlate { get; set; }
    }
}

我们的AutoMapper Profiles注册了三个映射:

        CreateMap<IVehicleModel, CarViewModel.Builder>();
        CreateMap<CarViewModel.Builder, IVehicleViewModel>().ConvertUsing(x => x.Build());
        CreateMap<IVehicleModel, IVehicleViewModel>().ConvertUsing<VehicleModelTypeConverter>();

VehicleModelTypeConverter然后定义了一个两阶段的转换:

    public IVehicleViewModel Convert(IVehicleModel source, IVehicleViewModel destination,
        ResolutionContext context)
    {
        var builder = context.Mapper.Map<CarViewModel.Builder>(source);
        var model = context.Mapper.Map<IVehicleViewModel>(builder);

        return model;
    }

ITypeListConverter<string, ILicensePlate>执行该映射)。

在我们的系统中使用是正常的:

var result = _mapper<IVehicleViewModel>(_carModel);

这是使用 AutoMapper v7.0.1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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