自动映射器映射异常映射类型:双精度 ->双精度



当我尝试在我的应用程序中调用 Mapper.Map 时,我收到以下异常:

AutoMapper.AutoMapperMappingException. 
Mapping types:
Double -> Double
System.Double -> System.Double
Destination path:
Address.Latitude
Source value:
42.250287
   System.InvalidCastException. Unable to cast object of type 'Acme.Order' to type 'Acme.Address'.

除了对指示它无法映射相同类型(以及原始类型)的对象的错误感到明显的沮丧之外,事实是我从未从类型"Acme.Order"映射到类型"Acme.Address"!

以下是正在使用的实际调用:

var order = Mapper.Map<IDataRecord, Order>(theDataReader);

我的对象模型如下所示:

public class Order
{
    public Address Address { get; set; }
    public Int32 Number { get; set; }
    public PhoneNumber PhoneNumber { get; set; }
}
public class Address
{
    public String City { get; set; }
    public Double Latitude { get; set; }
    public Double Longitude { get; set; }
    public Int32 Number { get; set; }
    public String PostalCode { get; set; }
    public String State { get; set; }
    public String Street { get; set; }
}
public class PhoneNumber
{
    public String Extension { get; set; }
    public String Number { get; set; }
}

我的应用程序中定义了以下配置:

CreateMap<IDataRecord, Address>()
.ForMember(target => target.Latitude, opt => opt.MapFrom(record => GetDoubleFrom(record, "Latitude", 0)))
.ForMember(target => target.Longitude, opt => opt.MapFrom(record => GetDoubleFrom(record, "Longitude", 0)))
;
CreateMap<IDataRecord, PhoneNumber>()
.ForMember(target => target.Extension, opt => opt.MapFrom(record => GetStringFrom(record, "Extension", String.Empty)))
.ForMember(target => target.Number, opt => opt.MapFrom(record => GetStringFrom(record, "PhoneNumber", String.Empty)))
;
CreateMap<IDataRecord, Order>()
.ForMember(target => target.Address, opt => opt.ResolveUsing(record => Mapper.Map<IDataRecord, Address>(record)))
.ForMember(target => target.PhoneNumber, opt => opt.ResolveUsing(record => Mapper.Map<IDataRecord, PhoneNumber>(record)))
;

使用这些帮助程序方法:

private Double GetDoubleFrom(IDataRecord record, String name, Double defaultValue)
{
    return (record.Contains(name) && !record.IsDbNull(name)) ? record.GetDouble(name) : defaultValue;
}
private String GetStringFrom(IDataRecord record, String name, String defaultValue)
{
    return (record.Contains(name) && !record.IsDbNull(name)) ? record.GetString(name) : defaultValue;
}

(我在 IDataRecord 上有扩展方法,这些方法采用字段名称、获取序号并使用标准方法返回值,但为简洁起见不会显示它们。

这是否揭示了导致故障的原因?

(顺便说一句,我正在使用自动映射器 v2.1.267)

我无法直接重新创建它,因为它缺少一些信息(例如IDataRecord接口的具体类、theDataReader的内容等)。但是,第一个检查是确保您的映射正确。你用AssertConfigurationIsValid测试它吗?

例如,如果您有以下自动映射器配置文件:

public class MyProfile : Profile
{
    public override string ProfileName
    {
        get
        {
            return "MyProfile";
        }
    }
    protected override void Configure()
    {
        CreateMap<IDataRecord, Address>()
            .ForMember(
                target => target.Latitude,
                opt => opt.MapFrom(
                    record => GetDoubleFrom(record, "Latitude", 0)))
            .ForMember(
                target => target.Longitude,
                opt => opt.MapFrom(
                    record => GetDoubleFrom(record, "Longitude", 0)));
        CreateMap<IDataRecord, PhoneNumber>()
            .ForMember(
                target => target.Extension,
                opt => opt.MapFrom(
                    record => GetStringFrom(record, "Extension", string.Empty)))
            .ForMember(
                target => target.Number,
                opt => opt.MapFrom(
                    record => GetStringFrom(record, "PhoneNumber", string.Empty)));
        CreateMap<IDataRecord, Order>()
            .ForMember(
                target => target.Address,
                opt => opt.ResolveUsing(
                    record => Mapper.Map<IDataRecord, Address>(record)))
            .ForMember(
                target => target.PhoneNumber,
                opt => opt.ResolveUsing(
                    record => Mapper.Map<IDataRecord, PhoneNumber>(record)));
    }
}

此单元测试会通过吗?

[Test]
public void AutoMapper_Configuration_IsValid()
{
    Mapper.Initialize(m => m.AddProfile<MyProfile>());
    Mapper.AssertConfigurationIsValid();
}

更新

你能试试吗

CreateMap<IDataRecord, Order>()
    .ForMember(
        target => target.Address,
        opt => opt.MapFrom(record => Mapper.Map<IDataRecord, Address>(record)))
    .ForMember(
        target => target.PhoneNumber,
        opt => opt.MapFrom(record => Mapper.Map<IDataRecord, PhoneNumber>(record)));

相关内容

最新更新