Automapper 将 2 类 配置为 1
Automapper configure 2 classes to one
我有以下数据库(基础设施)类:
[Table("ApplicationDriverEquipments")]
public partial class ApplicationDriverEquipment
{
public int Id { get; set; }
[StringLength(256)]
public string Make { get; set; }
[StringLength(256)]
public string Model { get; set; }
[StringLength(256)]
public string Year { get; set; }
[StringLength(256)]
public string VINNumber { get; set; }
[StringLength(256)]
public string PlateNumber { get; set; }
[StringLength(256)]
public string CurrentMileage { get; set; }
[StringLength(256)]
public string Length { get; set; }
public int TypeId { get; set; }
public virtual ApplicationDriverEquipmentType Type { get; set; }
public int DriverId { get; set; }
public virtual ApplicationDriver Driver { get; set; }
}
[Table("ApplicationDriverEquipmentTypes")]
public partial class ApplicationDriverEquipmentType
{
public ApplicationDriverEquipmentType()
{
Equipments = new HashSet<ApplicationDriverEquipment>();
}
public int Id { get; set; }
[Required]
[StringLength(256)]
public string Name { get; set; }
public virtual ICollection<ApplicationDriverEquipment> Equipments { get; set; }
}
和以下 DTO(域)类:
public abstract class ApplicationDriverEquipmentAbstractDomain
{
public int Id { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public string Year { get; set; }
public string PlateNumber { get; set; }
public string CurrentMileage { get; set; }
public string Type { get; protected set; }
}
public class ApplicationDriverEquipmentTractorDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentTractorDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor;
}
public string VINNumber { get; set; }
}
public class ApplicationDriverEquipmentTrailerDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentTrailerDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer;
}
public string Length { get; set; }
}
public class ApplicationDriverEquipmentStraightTruckDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentStraightTruckDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck;
}
public string VINNumber { get; set; }
public string Length { get; set; }
}
public class ApplicationDriverEquipmentCargoVanDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentCargoVanDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan;
}
public string VINNumber { get; set; }
public string Length { get; set; }
}
public static class ApplicationDriverEquipmentTypeStaticStringsDomain
{
public const string Tractor = "Tractor";
public const string Trailer = "Trailer";
public const string StraightTruck = "Straight Truck";
public const string CargoVan = "Cargo Van";
}
我写了下面的Automapper规则来解决它:
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTractorDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor));
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTrailerDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer));
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentStraightTruckDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck));
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentCargoVanDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan));
我收到一个错误:
Expression 'c => c.Type.Name' must resolve to top-level member and not
any child object's properties. Use a custom resolver on the child type
or the AfterMap option instead.
更新
我重写了地图:
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTractorDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest)=> dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor);
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTrailerDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest) => dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer);
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentStraightTruckDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest) => dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck);
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentCargoVanDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest) => dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan);
但现在我得到一个错误:
Type Map configuration: ApplicationDriverEquipmentTractorDomain ->
ApplicationDriverEquipment
Domain.POCO.Application.ApplicationDriverEquipmentTractorDomain ->
Infrastructure.Asset.ApplicationDriverEquipment
Property: Type ---> AutoMapper.AutoMapperMappingException: Missing
type map configuration or unsupported mapping.
Mapping types:
String -> ApplicationDriverEquipmentType
System.String -> Infrastructure.Asset.ApplicationDriverEquipmentType
好像,我没看懂怎么正确映射
尝试使用 MapFrom
方法:
.ForMember(c => c.Type.Name, p => p.MapFrom(s => Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor));
您正在尝试映射自
ApplicationDriverEquipmentTractorDomain.Type
是一个 string
至
ApplicationDriverEquipment.Type
是一个 ApplicationDriverEquipmentType
你的映射配置在哪里?
甚至可以将字符串映射到 ApplicationDriverEquipmentType
吗?
当然,你可以有一个 string Name
,但是你从哪里得到 Id
和 Equipments
?
我怀疑您不想在每次映射时都创建该类型的新实例,而是您需要从某个字典中查找实例,类似于 registry pattern
要实现这个想法,您只需要
- 从 DB
加载所有 ApplicationDriverEquipmentType
- 将它们放入字典中(假设名称是唯一的)
- 注册一个custom type converter or custom value resolver如下
实现这一点的一种方法是使用 custom type converter
你可以使用像
这样的东西
void ConvertUsing(Func<TSource, TDestination> mappingFunction);
并放入您自己的函数,该函数将按名称解析您的 ApplicationDriverEquipmentType
,假设名称是唯一的,如下所示:
var applicationEquipments = new ApplicationDriverEquipmentTypeRepository().FindAll(); // get all the values somehow from db
var dictionary = applicationEquipments.ToDictionary(x=>x.Name);
Func<string, ApplicationDriverEquipmentType> resolver = x=>dictionary[x];
另一种方法是使用 custom value resolver
本质上,这个想法是一样的——预加载对象的映射,只是你 "plug it in" 的方式不同
我有以下数据库(基础设施)类:
[Table("ApplicationDriverEquipments")]
public partial class ApplicationDriverEquipment
{
public int Id { get; set; }
[StringLength(256)]
public string Make { get; set; }
[StringLength(256)]
public string Model { get; set; }
[StringLength(256)]
public string Year { get; set; }
[StringLength(256)]
public string VINNumber { get; set; }
[StringLength(256)]
public string PlateNumber { get; set; }
[StringLength(256)]
public string CurrentMileage { get; set; }
[StringLength(256)]
public string Length { get; set; }
public int TypeId { get; set; }
public virtual ApplicationDriverEquipmentType Type { get; set; }
public int DriverId { get; set; }
public virtual ApplicationDriver Driver { get; set; }
}
[Table("ApplicationDriverEquipmentTypes")]
public partial class ApplicationDriverEquipmentType
{
public ApplicationDriverEquipmentType()
{
Equipments = new HashSet<ApplicationDriverEquipment>();
}
public int Id { get; set; }
[Required]
[StringLength(256)]
public string Name { get; set; }
public virtual ICollection<ApplicationDriverEquipment> Equipments { get; set; }
}
和以下 DTO(域)类:
public abstract class ApplicationDriverEquipmentAbstractDomain
{
public int Id { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public string Year { get; set; }
public string PlateNumber { get; set; }
public string CurrentMileage { get; set; }
public string Type { get; protected set; }
}
public class ApplicationDriverEquipmentTractorDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentTractorDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor;
}
public string VINNumber { get; set; }
}
public class ApplicationDriverEquipmentTrailerDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentTrailerDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer;
}
public string Length { get; set; }
}
public class ApplicationDriverEquipmentStraightTruckDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentStraightTruckDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck;
}
public string VINNumber { get; set; }
public string Length { get; set; }
}
public class ApplicationDriverEquipmentCargoVanDomain : ApplicationDriverEquipmentAbstractDomain
{
public ApplicationDriverEquipmentCargoVanDomain()
{
Type = ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan;
}
public string VINNumber { get; set; }
public string Length { get; set; }
}
public static class ApplicationDriverEquipmentTypeStaticStringsDomain
{
public const string Tractor = "Tractor";
public const string Trailer = "Trailer";
public const string StraightTruck = "Straight Truck";
public const string CargoVan = "Cargo Van";
}
我写了下面的Automapper规则来解决它:
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTractorDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor));
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTrailerDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer));
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentStraightTruckDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck));
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentCargoVanDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.ForMember(c => c.Type.Name, p => p.UseValue<string>(Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan));
我收到一个错误:
Expression 'c => c.Type.Name' must resolve to top-level member and not any child object's properties. Use a custom resolver on the child type or the AfterMap option instead.
更新
我重写了地图:
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTractorDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest)=> dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor);
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentTrailerDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest) => dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer);
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentStraightTruckDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest) => dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck);
CreateMap<Domain.POCO.Application.ApplicationDriverEquipmentCargoVanDomain, Infrastructure.Asset.ApplicationDriverEquipment>()
.AfterMap((src, dest) => dest.Type.Name = Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan);
但现在我得到一个错误:
Type Map configuration: ApplicationDriverEquipmentTractorDomain -> ApplicationDriverEquipment Domain.POCO.Application.ApplicationDriverEquipmentTractorDomain -> Infrastructure.Asset.ApplicationDriverEquipment
Property: Type ---> AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types:
String -> ApplicationDriverEquipmentType
System.String -> Infrastructure.Asset.ApplicationDriverEquipmentType
好像,我没看懂怎么正确映射
尝试使用 MapFrom
方法:
.ForMember(c => c.Type.Name, p => p.MapFrom(s => Domain.StaticStrings.ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor));
您正在尝试映射自
ApplicationDriverEquipmentTractorDomain.Type
是一个 string
至
ApplicationDriverEquipment.Type
是一个 ApplicationDriverEquipmentType
你的映射配置在哪里?
甚至可以将字符串映射到 ApplicationDriverEquipmentType
吗?
当然,你可以有一个 string Name
,但是你从哪里得到 Id
和 Equipments
?
我怀疑您不想在每次映射时都创建该类型的新实例,而是您需要从某个字典中查找实例,类似于 registry pattern
要实现这个想法,您只需要
- 从 DB 加载所有
- 将它们放入字典中(假设名称是唯一的)
- 注册一个custom type converter or custom value resolver如下
ApplicationDriverEquipmentType
实现这一点的一种方法是使用 custom type converter
你可以使用像
这样的东西
void ConvertUsing(Func<TSource, TDestination> mappingFunction);
并放入您自己的函数,该函数将按名称解析您的 ApplicationDriverEquipmentType
,假设名称是唯一的,如下所示:
var applicationEquipments = new ApplicationDriverEquipmentTypeRepository().FindAll(); // get all the values somehow from db
var dictionary = applicationEquipments.ToDictionary(x=>x.Name);
Func<string, ApplicationDriverEquipmentType> resolver = x=>dictionary[x];
另一种方法是使用 custom value resolver
本质上,这个想法是一样的——预加载对象的映射,只是你 "plug it in" 的方式不同