本文介绍了需要映射成员和构造函数的自动映射器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我是AutoMapper的新手,我只是想找出做事情的最佳方式。
我很快就遇到了两个简单但真实的对象模型之间的映射问题。第一个用于服务层: public sealed class GeoLocation { public GeoLocation( double latitude, double longitude) { this.Latitude = latitude; this.Longitude = longitude; } public double Latitude { get; private set; } public double Longitude { get; private set; } } public sealed class Location { public Location( string name, GeoLocation geoLocation) { this.Name = name; this.GeoLocation = geoLocation; } public string Name { get; private set; } public GeoLocation GeoLocation { get; private set; } }第二个是上述数据库层的简化表示:
public sealed class LocationEntity { public LocationEntity( string name, double latitude, double longitude) { this.Name = name; this.Latitude = latitude; this.Longitude = longitude; } public string Name { get; } public double Latitude { get; } public double Longitude { get; } }如果我尝试使用简单的CreateMap<Location, LocationEntity>().ReverseMap()调用来映射类型,则可以预见在验证映射时会出现问题:
AutoMapperConfigurationException: Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters =============================================== Location -> LocationEntity (Destination member list) UserQuery+Location -> UserQuery+LocationEntity (Destination member list) No available constructor. =============================================== LocationEntity -> Location (Destination member list) UserQuery+LocationEntity -> UserQuery+Location (Destination member list) Unmapped properties: GeoLocation No available constructor.很公平。我不想映射每个构造函数参数,所以我尝试调用ConstructUsing:
Mapper.Initialize( config => { config .CreateMap<Location, LocationEntity>() .ConstructUsing((source, _) => new LocationEntity(source.Name, source.GeoLocation?.Latitude ?? 0.0, source.GeoLocation?.Longitude ?? 0)); config .CreateMap<LocationEntity, Location>() .ConstructUsing((source, _) => new Location(source.Name, new GeoLocation(source.Latitude, source.Longitude))); });但是,这仍然抱怨LocationEntity->Location映射:
AutoMapperConfigurationException: Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters =============================================== LocationEntity -> Location (Destination member list) UserQuery+LocationEntity -> UserQuery+Location (Destination member list) Unmapped properties: GeoLocation不确定还能做什么,我添加了对LocationEntity->Location映射的ForMember调用:
config .CreateMap<LocationEntity, Location>() .ConstructUsing((source, _) => new Location(source.Name, new GeoLocation(source.Latitude, source.Longitude))) .ForMember( x => x.GeoLocation, options => options.MapFrom((source, target, _, context) => new GeoLocation(source.Latitude, source.Longitude))); 虽然这解决了问题,但在我看来,我的映射已经变得有些复杂了。我在想:有没有更好的方法来做这件事,而不牺牲我的对象模型的设计? 推荐答案您的对象模型设计基本上只允许通过构造进行映射(转换),因此无法充分利用AutoMapper自动和显式映射功能。
ConstructUsing用于选择用于创建目标实例的非默认构造函数,但仍需要成员映射。
您需要的是ConvertUsing方法:
跳过成员映射并使用自定义表达式转换为目标类型
Mapper.Initialize(config => { config.CreateMap<Location, LocationEntity>() .ConvertUsing(source => new LocationEntity(source.Name, source.GeoLocation?.Latitude ?? 0.0, source.GeoLocation?.Longitude ?? 0)); config.CreateMap<LocationEntity, Location>() .ConvertUsing(source => new Location(source.Name, new GeoLocation(source.Latitude, source.Longitude))); });更多推荐
需要映射成员和构造函数的自动映射器
发布评论