如何指定自动映射器异常导致的数据?
How to specify automapper exception caused data?
我正在使用第三个工具从文件中读取坐标值,该工具将数据投射到 Point
class 集合。
public class Point
{
public string Lon {get;set;}
public string Lat {get;set;}
public string Elevation {get;set;}
}
我想使用自动映射器将 Point
class 映射到 PointEntity
。
public class PointEntity
{
public float Lon {get;set;}
public float Lat {get;set;}
public float Elevation {get;set;}
}
我使用 Automapper 创建了一个地图。
public class LocationProfile : Profile
{
public LocationProfile()
{
CreateMap<Point, PointEntity>();
}
}
并且我已经创建了一个映射列表的通用映射器扩展。
public static class MapperHelper
{
public static TDest MapTo<TDest>(this object src)
{
return (TDest)AutoMapper.Mapper.Map(src, src.GetType(), typeof(TDest));
}
}
IList<Point> data = readData<Point>("file");
var mapped = data.MapTo<PointEntity>();
但有时用户可能会在文件中输入错误的条目,如下所示。
Lon Lat Elevation
--- --- ---------
11.5 25.6 80.56
12ab 89.87 14.83
1.7 x.8 9.3
在这种情况下,代码抛出异常。
那么我怎样才能找到错误类型的行和值呢? (例如row1和Lon值是错误的)
改变你的设计思路。映射只是将一个数据传输到另一个数据。 automapper 非常擅长这项任务。把事情简单化。所以,尽量保持简单。我读到您想在映射期间执行验证并提供相关信息。这使得映射更加复杂。在我的设计中,我不会让这种情况在映射过程中发生。在映射之前验证此信息。在使用验证规则 class 进行映射之前对其进行迭代。或在读取时验证数据,以便您可以立即告知行和列位置。
例子
使用 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);
}
}
为什么要使用委托?
通过收集所有(也为每个参数[lon,lat,...])无效参数的其他示例。
在这里看到现在使用处理程序的力量。
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);
}
我正在使用第三个工具从文件中读取坐标值,该工具将数据投射到 Point
class 集合。
public class Point
{
public string Lon {get;set;}
public string Lat {get;set;}
public string Elevation {get;set;}
}
我想使用自动映射器将 Point
class 映射到 PointEntity
。
public class PointEntity
{
public float Lon {get;set;}
public float Lat {get;set;}
public float Elevation {get;set;}
}
我使用 Automapper 创建了一个地图。
public class LocationProfile : Profile
{
public LocationProfile()
{
CreateMap<Point, PointEntity>();
}
}
并且我已经创建了一个映射列表的通用映射器扩展。
public static class MapperHelper
{
public static TDest MapTo<TDest>(this object src)
{
return (TDest)AutoMapper.Mapper.Map(src, src.GetType(), typeof(TDest));
}
}
IList<Point> data = readData<Point>("file");
var mapped = data.MapTo<PointEntity>();
但有时用户可能会在文件中输入错误的条目,如下所示。
Lon Lat Elevation
--- --- ---------
11.5 25.6 80.56
12ab 89.87 14.83
1.7 x.8 9.3
在这种情况下,代码抛出异常。
那么我怎样才能找到错误类型的行和值呢? (例如row1和Lon值是错误的)
改变你的设计思路。映射只是将一个数据传输到另一个数据。 automapper 非常擅长这项任务。把事情简单化。所以,尽量保持简单。我读到您想在映射期间执行验证并提供相关信息。这使得映射更加复杂。在我的设计中,我不会让这种情况在映射过程中发生。在映射之前验证此信息。在使用验证规则 class 进行映射之前对其进行迭代。或在读取时验证数据,以便您可以立即告知行和列位置。
例子
使用 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);
}
}
为什么要使用委托? 通过收集所有(也为每个参数[lon,lat,...])无效参数的其他示例。 在这里看到现在使用处理程序的力量。
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);
}