Измените свое дизайнерское мышление. Отображение — это просто перенос одних данных в другие данные. И automapper отлично справляется с этой задачей. Будь проще. Итак, держите это как можно проще. Я читал, что вы хотите выполнить проверку во время сопоставления и предоставить информацию об этом. Это делает отображение более сложным. В моем дизайне я бы не позволил этому случиться во время отображения. Проверьте эту информацию перед сопоставлением. Повторите это перед отображением с помощью класса правила проверки. Или проверяет данные во время чтения, чтобы вы могли сразу сообщить позицию строки и столбца.
Пример
Используйте ConvertUsing (но не требуется, если он был проверен ранее) Шаг к реализации
public class LocationProfile : Profile
{
public LocationProfile()
{
CreateMap<Point, PointEntity>().ConvertUsing<PointEntityConverter>();
}
}
public class PointEntityConverter : ITypeConverter<Point, PointEntity>
{
public PointEntity Convert(Point source, PointEntity destination, ResolutionContext context)
{
if (destination == null)
destination = new PointEntity();
destination.Lon = Parse(source.Lon, nameof(source.Lon));
destination.Lat = Parse(source.Lat, nameof(source.Lat));
destination.Elevation = Parse(source.Elevation, nameof(source.Elevation));
return destination;
}
private float Parse(string s, string paramName)
{
if (float.TryParse(s, out float result))
return result;
throw new ArgumentException($"Invalide value ({s}) for parameter {paramName}", paramName);
}
Реализация
private readonly IMapper mapper;
private readonly IValidator<Point> validator;
public HowToSpecifyAutomapperExceptionCausedData(IMapper mapper)
{
this.mapper = mapper;
this.validator = new PointValidator();
}
public void Example()
{
var data = readData<Point>("file");
for (int i = 0; i < data.Count; i++)
validator.AssertValide(data[i], (m, p) => OnInvalidArgument(m, p, i));
var mapped = mapper.Map<IList<PointEntity>>(data);
}
private void OnInvalidArgument(string message, string paramName, int index)
{
throw new ArgumentException($"{message} on index {index}", paramName);
}
Валидатор
internal interface IValidator<T>
{
void AssertValide(T value, InvalideArgumentHandler handler);
}
internal delegate void InvalideArgumentHandler(string message, string paramName);
internal class PointValidator : IValidator<Point>
{
public void AssertValide(Point value, InvalideArgumentHandler handler)
{
AssertValideFloat(value.Lon, nameof(value.Lon), handler);
AssertValideFloat(value.Lat, nameof(value.Lat), handler);
AssertValideFloat(value.Elevation, nameof(value.Elevation), handler);
}
private void AssertValideFloat(string s, string paramName, InvalideArgumentHandler handler)
{
if (!float.TryParse(s, out float result))
handler($"Invalide value ({s}) for parameter {paramName}", paramName);
}
}
Зачем использовать делегат? Другой пример: сбор всех (также для каждого параметра [долгота, широта, ...]) недействительных параметров. Вот теперь посмотрите на силу, использующую для этого обработчик.
public void Example()
{
var data = readData<Point>("file");
var errors = new List<string>();
for (int i = 0; i < data.Count; i++)
validator.AssertValide(data[i], (m, p) => errors.Add($"{m} on index {i}"));
if (errors.Any()) //using System.Linq;
throw new ApplicationException(string.Join(Environment.NewLine, errors));
var mapped = mapper.Map<IList<PointEntity>>(data);
}
person
Roberto B
schedule
25.05.2021