C#类层次结构下,如何实现DTO与领域对象的属性映射?
问题描述
简介
简单来说,假设领域层有3个类(我称之为业务对象BO),此处省略构造函数等内容,仅保留相关属性:
public class VehicleBo { public string Manufacturer { get; set; } } public class CarBo : VehicleBo { public int PassengerCount { get; set; } } public class TruckBo : VehicleBo { public double MaximumLoad { get; set; } public bool HasTrailer { get; set; } }
我们有一个DTO对象聚合了BO层次结构中的所有属性:
public class VehicleDto { public string Manufacturer { get; set; } public int PassengerCount { get; set; } public double MaximumLoad { get; set; } public bool HasTrailer { get; set; } // 对应EF Core中VehicleBo映射数据库时定义的鉴别器 public string VehicleType { get; set; } }
我们使用Entity Framework Core将BO映射到关系数据库表,所有BO(VehicleBo、CarBo、TruckBo)共用一张Vehicles表,采用Table per hierarchy(TPH)(单表继承)策略存储。
背景逻辑
用户查看Vehicles表内容时看到的是VehicleDto数据,前端过滤排序请求会由一个小型框架处理,该框架通过属性名匹配将DTO属性映射到BO属性。
例如前端发送过滤请求(符号代码):
{ Type: VehicleDto, Predicate: v => v.Manufacturer == "Ford" }
框架会转换为:
{ Type: VehicleBo, Predicate: v => v.Manufacturer == "Ford" }
(注意此处类型为VehicleBo而非VehicleDto)并发送到后端。这种情况在属性名一致时可行,但像PassengerCount这类仅存在于子类CarBo的属性无法直接映射。
前端发送:
{ Type: VehicleDto, Predicate: v => v.PassengerCount > 2 }
框架无法转换为v => v.PassengerCount > 2(因VehicleBo无该属性),实际需要转换为:
{ Type: VehicleBo, Predicate: v => ((CarBo) v).PassengerCount > 2 }
EF Core可将其转换为SQL查询,这一逻辑可行。
问题挑战
我需要一种优雅的方式为框架提供DTO到BO的映射提示。最初考虑使用泛型属性,但C#不支持将表达式作为属性参数,只能使用字符串形式,这种方式繁琐且易出错。
请问有没有既优雅又简单且类型安全的解决方案?
内容的提问来源于stack exchange,提问作者Pavel Foltyn
相关产品推荐
相关产品推荐

