Я новичок в 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
Не зная, что еще делать, я добавил ForMember
вызов к отображению LocationEntity
-> Location
:
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)));
Хотя это решает проблему, мне кажется, что мойотображения уже становятся несколько сложными.Мне интересно: есть ли лучший способ сделать это, не жертвуя дизайном моих объектных моделей?