本文介绍了需要映射成员和构造函数的自动映射器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我是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)));
});
这篇关于需要映射成员和构造函数的自动映射器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!