简体   繁体   English

自动映射器和不变性

[英]Automapper and immutability

Is it possible to use AutoMapper with Immutable types?是否可以将 AutoMapper 与不可变类型一起使用?

For example my Domain type is immutable and I want to map my view type to this.例如我的域类型是不可变的,我想将我的视图类型映射到这个。

I believe it is not but just want this confirmed.我相信它不是,但只是想确认这一点。

Also as it is best practice to have your domain types immutable, what is the best practice when mapping your view types to domain types?此外,由于域类型不可变是最佳实践,因此将视图类型映射到域类型时的最佳实践是什么?

I typically do the mapping from view types to domain types by hand, as I'll typically be working through a more complex interface, using methods and so on.我通常手动进行从视图类型到域类型的映射,因为我通常会通过更复杂的接口、使用方法等进行工作。 If you use AutoMapper to go from view to domain, you're now locked in to an anemic domain model, whether you've intentionally decided to or not.如果您使用 AutoMapper 从视图到域,您现在被锁定在一个贫血的域模型中,无论您是否有意决定。

Suppose that you really did want an immutable property on your Domain type, say Id .假设您确实想要域类型的不可变属性,例如Id Your domain type might look something like this:您的域类型可能如下所示:

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

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

Then you can use ConstructUsing using a public constructor of your choice, such as:然后,您可以使用您选择的公共构造函数来使用ConstructUsing ,例如:

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

Then map all the mutable properties in the normal way然后以正常方式映射所有可变属性

AutoMapper relies on property setters to do its work, so if you have read-only properties, AutoMapper won't be of much use. AutoMapper 依赖属性设置器来完成它的工作,所以如果你有只读属性,AutoMapper 将没有多大用处。

You could override the mapping behaviour and, for example, configure it to invoke a specific constructor, but that basically defeats the purpose of AutoMapper because then you are doing the mapping manually, and you've only succeeded in adding a clumsy extra step in the process.您可以覆盖映射行为,例如,将其配置为调用特定的构造函数,但这基本上违背了 AutoMapper 的目的,因为那时您正在手动进行映射,并且您只能成功地在过程。

It doesn't make a lot of sense to me that your domain model is immutable.你的域模型是不可变的,这对我来说没有多大意义。 How do you update it?你如何更新它? Is the entire application read-only?整个应用程序是只读的吗? And if so, why would you ever need to map to your domain model as opposed to from ?如果是这样,为什么您需要映射域模型而不是from An immutable domain model sounds... pretty useless.一个不可变的域模型听起来……很没用。

PS I'm assuming that you mean this AutoMapper and not the auto-mapping feature in Fluent NHibernate or even some other totally different thing. PS 我假设你的意思是这个 AutoMapper而不是Fluent NHibernate 中自动映射功能,甚至是其他一些完全不同的东西。 If that's wrong then you should be more specific and add tags for your platform/language.如果那是错误的,那么您应该更具体并为您的平台/语言添加标签。

We have immutable objects using the builder pattern.我们有使用构建器模式的不可变对象。 Mapping them takes a little more boilerplate code, but it is possible映射它们需要更多的样板代码,但这是可能的

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

Our AutoMapper Profiles have three mappings registered:我们的AutoMapper Profiles注册了三个映射:

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

The VehicleModelTypeConverter then defines a two stage conversion: 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;
    }

(An implementation of ITypeListConverter<string, ILicensePlate> carries out that mapping). ITypeListConverter<string, ILicensePlate>执行该映射)。

Usage in our system is as normal:在我们的系统中使用是正常的:

var result = _mapper<IVehicleViewModel>(_carModel);

This is using AutoMapper v7.0.1这是使用 AutoMapper v7.0.1

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

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