簡體   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