我正在创建一个简单的 MVC4 应用程序
我有一个自动映射器
Mapper.CreateMap<SourceClass, DestinationClass>()
.ForMember(dest => dest.IntphoneNo,
opt => opt.MapFrom(src => src.Stringphoneno));
IntphoneNo是DataTypeint(IntphoneNo是我的类的变量
Person
)
源属性 Stringphoneno 的数据类型为 string。
当我绘制地图时,出现以下错误。
AutoMapper.dll 中发生“AutoMapper.AutoMapperMappingException”类型的异常,但未在用户代码中处理
但是当我将IntphoneNo的数据类型从int更改为string时,我的程序就成功运行了。
不幸的是,我无法更改模型中的数据类型
有什么方法可以改变映射中的数据图.. 像下面这样
.ForMember(dest => dest.IntphoneNo,
opt => opt.MapFrom(src => src.Int32(Stringphoneno));
经过一番研究,我又向前迈进了一步..
如果我的 StringPhoneNo 是 = 123456
然后以下代码正在工作。我不需要将它解析为字符串
Mapper.CreateMap<SourceClass, DestinationClass>()
.ForMember(dest => dest.IntphoneNo,
opt => opt.MapFrom(src => src.Stringphoneno));
但是当我的 StringPhoneNo = 12 3456 (12 后面有一个 空格 )时,我的代码不起作用。 有没有办法在自动映射器中修剪 Stringphoneno 中的空格(Stringphoneno我从网络服务获取)。
像下面这样..
Mapper.CreateMap<SourceClass, DestinationClass>()
.ForMember(dest => dest.IntphoneNo,
opt => opt.MapFrom(src => src.Trim(Stringphoneno)));
Mapper.CreateMap<SourceClass, DestinationClass>()
.ForMember(dest => dest.IntphoneNo,
opt => opt.MapFrom(src => int.Parse(src.Stringphoneno)));
这里是一些使用所描述的地图的示例工作代码
class SourceClass
{
public string Stringphoneno { get; set; }
}
class DestinationClass
{
public int IntphoneNo { get; set; }
}
var source = new SourceClass {Stringphoneno = "8675309"};
var destination = Mapper.Map<SourceClass, DestinationClass>(source);
Console.WriteLine(destination.IntphoneNo); //8675309
您可能面临的问题是,当无法解析字符串时,一种选择是使用 ResolveUsing:
Mapper.CreateMap<SourceClass, DestinationClass>()
.ForMember(dest => dest.intphoneno, opts => opts.ResolveUsing(src =>
double.TryParse(src.strphoneno, out var phoneNo) ? phoneNo : default(double)));
Yuriy Faktorovich
的扩展方法并使用一些自定义属性,
string
的解决方案可以推广到所有应转换为 int
的 IMappingExpression
:
[AttributeUsage(AttributeTargets.Property)]
public class StringToIntConvertAttribute : Attribute
{
}
// tries to convert string property value to integer
private static int GetIntFromString<TSource>(TSource src, string propertyName)
{
var propInfo = typeof(TSource).GetProperty(propertyName);
var reference = (propInfo.GetValue(src) as string);
if (reference == null)
throw new MappingException($"Failed to map type {typeof(TSource).Name} because {propertyName} is not a string);
// TryParse would be better
var intVal = int.Parse(reference);
return intVal;
}
public static IMappingExpression<TSource, TDestination> StringToIntMapping<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var srcType = typeof(TSource);
foreach (var property in srcType.GetProperties().Where(p => p.GetCustomAttributes(typeof(StringToIntConvertAttribute), inherit: false).Length > 0))
{
expression.ForMember(property.Name, opt => opt.MapFrom(src => GetIntFromString(src, property.Name)));
}
return expression;
}
为了完成这项工作,必须执行以下步骤:
源和目标之间的映射必须附加映射扩展名。例如:
var config = new MapperConfiguration(cfg =>
{
// other mappings
cfg.CreateMap<SrcType, DestType>().StringToIntMapping();
});
将该属性应用于必须自动转换为整数值的所有源字符串属性
这是一种更简单但可扩展性较差的方法。每当您调用 Mapper.Initialize 时,请记住调用 .ToInt() 否则您将收到运行时错误。
public class NumberTest
{
public static void Main(string[] args)
{
Console.WriteLine("".ToInt());
// 0
Console.WriteLine("99".ToInt());
// 99
}
}
public static class StringExtensions
{
public static int ToInt(this string text)
{
int num = 0;
int.TryParse(text, out num);
return num;
}
}
// Use like so with Automapper
.ForMember(dest => dest.WidgetID, opts => opts.MapFrom(src => src.WidgetID.ToInt()));
如果您确定不需要处理异常。您可以尝试添加
PreCondition
,这将检查您的条件 (int.TryParse()
),并且仅在条件返回 true 时映射特定值。
CreateMap<Source, Target>().ForMember(x => x.StringToIntMember, option => option.PreCondition(y => int.TryParse(y.StringToIntMember, out int _)))
使用它,您可以安全地检查一个值是否可解析,请注意,这不会引发任何异常。因此,只有当您 100% 确定不处理异常不会造成任何损害时,才应使用它。
注意: 当值尚未映射时,这会将您的整数设置为 0。考虑让你的整数可以为空,这样它就设置为 null 而不是 0。这样你就可以在将字符串“0”映射到 0 和“qwerty”映射到 null 之间进行延迟。