1

アプリケーションで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には、フィールド名を取得し、序数を取得し、標準メソッドを使用して値を返す拡張メソッドがありますが、簡潔にするために表示しません。)

これのいずれかが失敗の原因に光を当てていますか?

(ところで、私はAutoMapper v2.1.267を使用しています)

4

1 に答える 1

1

IDataRecord一部の情報 (インターフェイスの具象クラス、 のコンテンツなど)が欠落しているため、これを直接再作成することはできませんtheDataReader。ただし、最初のチェックは、マッピングが正しいことを確認することです。でテストしAssertConfigurationIsValidますか?

たとえば、次の AutoMapper プロファイルがあるとします。

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)));
于 2012-11-28T23:34:42.330 に答える