是否可以将 AutoMapper 与不可变类型一起使用?
例如,我的 Domain 类型是不可变的,我想将我的视图类型映射到它。
我相信这不是但只是希望得到证实。
此外,最好的做法是让您的域类型不可变,将视图类型映射到域类型时的最佳做法是什么?
是否可以将 AutoMapper 与不可变类型一起使用?
例如,我的 Domain 类型是不可变的,我想将我的视图类型映射到它。
我相信这不是但只是希望得到证实。
此外,最好的做法是让您的域类型不可变,将视图类型映射到域类型时的最佳做法是什么?
我通常手动完成从视图类型到域类型的映射,因为我通常会通过更复杂的接口、使用方法等工作。如果您使用 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
您可以将 Automapper 与具有属性 init only setter 的类或记录一起使用。这是 C# 9.0 中的新功能。
Automapper 可以在对象创建时设置属性,因为属性只有 init 设置器,但是在 Automapper 映射它们之后,它们被锁定(不可变)。
https://www.tsunamisolutions.com/blog/c-90-records-and-dtos-a-match-made-in-redmond