能否将AutoMapper用于Immutable类型?
例如,我的领域类型是不可变的,我想将我的视图类型映射到这个类型。
我相信它不能,但只是想要确认一下。
此外,最佳实践是使领域类型不可变,那么在将视图类型映射到领域类型时,最佳实践是什么?
能否将AutoMapper用于Immutable类型?
例如,我的领域类型是不可变的,我想将我的视图类型映射到这个类型。
我相信它不能,但只是想要确认一下。
此外,最佳实践是使领域类型不可变,那么在将视图类型映射到领域类型时,最佳实践是什么?
通常我会手动将视图类型映射到领域类型,因为我通常会通过更复杂的接口、使用方法等方式进行工作。如果您使用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的目的,因为那样您就需要手动进行映射,并且在过程中添加了一个笨拙的额外步骤。
对我来说,您的领域模型是不可变的并不太合理。您如何更新它?整个应用程序都是只读的吗?如果是这样,为什么您需要映射到您的领域模型而不是从您的领域模型呢?一个不可变的领域模型听起来...相当无用。
P.S. 我假设您指的是这个AutoMapper,而不是Fluent NHibernate中的自动映射功能或其他完全不同的东西。如果我理解有误,请更具体地说明并为您的平台/语言添加标签。
你可以在具有只读属性的类或记录中使用Automapper。这是C# 9.0中的新功能。
由于这些属性具有只读setter,因此Automapper可以在对象创建时设置属性,但是在Automapper映射完它们之后,它们将被锁定(不可变)。
https://www.tsunamisolutions.com/blog/c-90-records-and-dtos-a-match-made-in-redmond
// 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; }
}
}
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