使用对象-对象映射器是一种好的做法吗?如果是,在哪里使用它?
Is it good practice to use object-object mappers, and, if so, where to use it?
我在互联网上进行了一些搜索,找到了一些关于该主题的文章,但其中 none 令我满意。我想知道使用对象-对象映射器将对象相互映射好不好?我知道这取决于使用情况,但我如何实现良好或最佳使用情况?
退一步说,最好的做法是将数据传输对象 (DTO) 和视图模型 (VM) 与业务对象(实体等)分开。在这方面,映射库是达到目的的一种手段,只是让这种关联变得更容易。
至于何时,由您决定。如果您觉得可以以易于维护的方式在您的业务模型和 DTO/VMs 之间转换,请继续。根据我个人的经验,这只是到目前为止(尤其是随着需求的变化)。因此,我喜欢映射库(特别是 AutoMapper,因为我知道它是 API 并且很乐意将其插入)。
话虽如此,每当我必须在这两个模型之间切换时,我都会使用 AutoMapper。我只需配置一次就可以了 运行。对模型(两侧)的额外调整变得更容易,因为我可以在一个地方(地图定义文件)和方法自动更改这些绑定 "catch up"。
示例:
我的数据库包含一个产品的记录:
class Product
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int QuantityOnHand { get; set; }
public int? ReorderQuantity { get; set; }
public string Sku { get; set; }
}
我可能会以更精炼的形式向 UI 展示这个:
public class ProductViewModel
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int Quantity { get; set; }
}
如果这来自某种存储库,我只是调用:
var model = Mapper.Map<ProductViewModel>(productFromRepository)
在这里,我始终从我请求的产品中获得我关心的视图模型。如果 business/service 层是 add/change/remove 属性,我只会回到我的 Mapper.CreateMap<Product, ProductViewModel>()
定义,但我的其他表示逻辑将保持原样。
除了@Brad Christie 的回答之外,如果您打算将它们与以不同方式生成的其他产品一起显示在您的视图中,将具有细微差异的自动映射类型自动映射到一个总体类型中通常会更容易。
如果你允许我抄写我自己以前的答案,这里有一个例子:
class SingleProduct {
string Name {get;set;}
decimal Price {get;set;}
decimal GetActualPrice() { return Price; }
}
class ComboSaleProduct {
string Name {get;set;}
List<SingleProduct> ComboProducts {get;set;}
decimal GetActualPrice() { return ComboProducts.Sum(p => p.GetActualPrice()); }
}
class ProductViewModel {
string Name {get;set;}
decimal ActualPrice {get;set;}
}
Automapper 将所有内容连接在一起,以便您可以 return 其中任何一个,它会自动将 "GetActualPrice" 映射到视图模型上的 ActualPrice。
我在互联网上进行了一些搜索,找到了一些关于该主题的文章,但其中 none 令我满意。我想知道使用对象-对象映射器将对象相互映射好不好?我知道这取决于使用情况,但我如何实现良好或最佳使用情况?
退一步说,最好的做法是将数据传输对象 (DTO) 和视图模型 (VM) 与业务对象(实体等)分开。在这方面,映射库是达到目的的一种手段,只是让这种关联变得更容易。
至于何时,由您决定。如果您觉得可以以易于维护的方式在您的业务模型和 DTO/VMs 之间转换,请继续。根据我个人的经验,这只是到目前为止(尤其是随着需求的变化)。因此,我喜欢映射库(特别是 AutoMapper,因为我知道它是 API 并且很乐意将其插入)。
话虽如此,每当我必须在这两个模型之间切换时,我都会使用 AutoMapper。我只需配置一次就可以了 运行。对模型(两侧)的额外调整变得更容易,因为我可以在一个地方(地图定义文件)和方法自动更改这些绑定 "catch up"。
示例:
我的数据库包含一个产品的记录:
class Product
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int QuantityOnHand { get; set; }
public int? ReorderQuantity { get; set; }
public string Sku { get; set; }
}
我可能会以更精炼的形式向 UI 展示这个:
public class ProductViewModel
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int Quantity { get; set; }
}
如果这来自某种存储库,我只是调用:
var model = Mapper.Map<ProductViewModel>(productFromRepository)
在这里,我始终从我请求的产品中获得我关心的视图模型。如果 business/service 层是 add/change/remove 属性,我只会回到我的 Mapper.CreateMap<Product, ProductViewModel>()
定义,但我的其他表示逻辑将保持原样。
除了@Brad Christie 的回答之外,如果您打算将它们与以不同方式生成的其他产品一起显示在您的视图中,将具有细微差异的自动映射类型自动映射到一个总体类型中通常会更容易。
如果你允许我抄写我自己以前的答案,这里有一个例子:
class SingleProduct {
string Name {get;set;}
decimal Price {get;set;}
decimal GetActualPrice() { return Price; }
}
class ComboSaleProduct {
string Name {get;set;}
List<SingleProduct> ComboProducts {get;set;}
decimal GetActualPrice() { return ComboProducts.Sum(p => p.GetActualPrice()); }
}
class ProductViewModel {
string Name {get;set;}
decimal ActualPrice {get;set;}
}
Automapper 将所有内容连接在一起,以便您可以 return 其中任何一个,它会自动将 "GetActualPrice" 映射到视图模型上的 ActualPrice。