10

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

例如,我的 Domain 类型是不可变的,我想将我的视图类型映射到它。

我相信这不是但只是希望得到证实。

此外,最好的做法是让您的域类型不可变,将视图类型映射到域类型时的最佳做法是什么?

4

5 回答 5

8

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

于 2010-02-04T04:05:36.300 回答
2

假设您确实想要域类型上的不可变属性,例如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));

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

于 2018-07-22T14:34:38.427 回答
1

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

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

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

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

于 2010-02-04T04:27:43.940 回答
0

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

// 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

于 2020-02-21T11:28:39.160 回答
0

您可以将 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

于 2021-09-15T17:07:32.160 回答