2010-01-12 77 views
6

更新1-13-10 我已經能夠找到一些成功使用下面的代碼進行映射。我基本上忽略了任何沒有映射的屬性,並在之後進行映射。我希望能夠以最好的方式迴應這個問題。另外,我不確定如何去執行這個映射的單元測試。我的印象是使用AutoMapper應該有助於減輕檢查每個屬性的乏味。Automapper自定義映射異常

這是我的新代碼:

Mapper.CreateMap<MoveEntity, MoveEntityDto>() 
      .ForMember(dest => dest.PrimaryOriginTransferee, opt => opt.Ignore()) 
      .ForMember(dest => dest.PrimaryDestinationTransferee, opt => opt.Ignore()) 
      .ForMember(dest => dest.Customer, opt => opt.Ignore()) 
      .ForMember(dest => dest.DestinationAddress, opt => opt.Ignore()) 
      .ForMember(dest => dest.OriginAddress, opt => opt.Ignore()) 
      .ForMember(dest => dest.Order, opt => opt.Ignore()) 
      .ForMember(dest => dest.Shipment, opt => opt.Ignore()) 
      .ForMember(dest => dest.SourceSystemName, opt => opt.Ignore()); 

     Mapper.CreateMap<ContactEntity, TransfereeEntityDto>(); 
     Mapper.CreateMap<CustomerEntity, CustomerEntityDto>(); 
     Mapper.CreateMap<AddressEntity, AddressEntityDto>(); 
     Mapper.CreateMap<OrderEntity, OrderEntityDto>() 
      .ForMember(dest => dest.OrderForwarding, opt => opt.Ignore()) 
      .ForMember(dest => dest.Forwarder, opt => opt.Ignore()); 
     Mapper.CreateMap<ShipmentEntity, ShipmentEntityDto>() 
      .ForMember(dest => dest.Services, opt => opt.Ignore()); 
     Mapper.CreateMap<ServiceEntity, ServiceEntityDto>() 
      .ForMember(dest => dest.ServiceTypeCode, opt => opt.Ignore()) //TODO: ServiceTypeCode not being mapped, should it? 
      .ForMember(dest => dest.SourceSystemName, opt => opt.MapFrom(src => Enum.GetName(typeof(SourceSystemName), src.SourceSystemName))); 
     Mapper.CreateMap<OrderForwardingEntity, OrderForwardingEntityDto>(); 


     Mapper.AssertConfigurationIsValid(); 


     MoveEntityDto moveEntityDto = Mapper.Map<MoveEntity, MoveEntityDto>(moveEntity); 
     moveEntityDto.PrimaryDestinationTransferee = Mapper.Map<ContactEntity, TransfereeEntityDto>(moveEntity.PrimaryDestinationTransferee); 
     moveEntityDto.PrimaryOriginTransferee = Mapper.Map<ContactEntity, TransfereeEntityDto>(moveEntity.PrimaryOriginTransferee); 
     moveEntityDto.Customer = Mapper.Map<CustomerEntity, CustomerEntityDto>(moveEntity.Customer); 
     moveEntityDto.DestinationAddress = Mapper.Map<AddressEntity, AddressEntityDto>(moveEntity.DestinationAddress); 
     moveEntityDto.OriginAddress = Mapper.Map<AddressEntity, AddressEntityDto>(moveEntity.OriginAddress); 
     moveEntityDto.Order = Mapper.Map<OrderEntity, OrderEntityDto>(moveEntity.Order); 
     moveEntityDto.Order.OrderForwarding = Mapper.Map<OrderForwardingEntity, OrderForwardingEntityDto>(moveEntity.Order.OrderForwarding); 
     //moveEntityDto.Order.Forwarder = Mapper.Map<ForwarderEntity, ForwarderEntityDto>(moveEntity.Order.Forwarder); //Apparently there is no forwarder entity for an Order 
     moveEntityDto.Shipment = Mapper.Map<ShipmentEntity, ShipmentEntityDto>(moveEntity.Shipment); 
     moveEntityDto.Shipment.Services = Mapper.Map<ServiceEntity[], ServiceEntityDto[]>(moveEntity.Shipment.ServiceEntities); 

原貼:

我試圖使用AutoMapper首次以從經營業務對象的映射DTO。我跑,到我不知道如何解決的問題,包括以下情況除外:

AutoMapper.AutoMapperMappingException:試圖Graebel.SP.BO.MoveEntity映射到Graebel.SOA.Contracts.DataContracts.SP。 MoveEntity。類型 異常 'AutoMapper.AutoMapperMappingException' 被拋出

這裏是AutoMapper代碼,我運行:

public MoveEntityDto MapMoveEntityToMoveEntityDto(MoveEntity moveEntity) 
    { 
     Mapper.CreateMap<MoveEntity, MoveEntityDto>() 
      .ForMember(dest => dest.PrimaryOriginTransferee, opt => opt.MapFrom(src => src.PrimaryOriginTransferee)) 
      .ForMember(dest => dest.PrimaryDestinationTransferee,opt => opt.MapFrom(src => src.PrimaryDestinationTransferee)) 
      .ForMember(dest => dest.Customer, opt => opt.MapFrom(src => src.Customer)) 
      .ForMember(dest => dest.DestinationAddress, opt => opt.MapFrom(src => src.DestinationAddress)) 
      .ForMember(dest => dest.Order, opt => opt.MapFrom(src => src.Order)) 
      .ForMember(dest => dest.OriginAddress, opt => opt.MapFrom(src => src.OriginAddress)) 
      .ForMember(dest => dest.Shipment, opt => opt.MapFrom(src => src.Shipment)) 
      .ForMember(dest => dest.SourceSystemName, opt => opt.Ignore()); 

     Mapper.AssertConfigurationIsValid(); 
     MoveEntityDto moveEntityDto = Mapper.Map<MoveEntity, MoveEntityDto>(moveEntity); 

     return moveEntityDto; 
    } 

這裏是DTO(MoveEntityDto),我嘗試映射:

public class MoveEntityDto 
{  
    public bool IsOrderDetailPageModified { get; set; } 
    public bool IsRoutingPageModified { get; set; } 
    public bool IsServicePageModified { get; set; } 
    public bool IsContentAndContainerPageModified { get; set; } 
    public string FamilyRange { get; set; } 
    public string Office { get; set; } 
    public string ActivityType { get; set; } 
    public string ActivitySubject { get; set; } 
    public string ActivityNote { get; set; } 
    public TransfereeEntity PrimaryOriginTransferee { get; set; } 
    public TransfereeEntity PrimaryDestinationTransferee { get; set; } 
    public CustomerEntity Customer { get; set; } 
    public AddressEntity OriginAddress { get; set; } 
    public AddressEntity DestinationAddress { get; set; } 
    public OrderEntity Order { get; set; } 
    public ShipmentEntity Shipment { get; set; } 
    public string PortalId { get; set; } 
    public string SourceSystemId { get; set; } 
    public EnterpriseEnums.SourceSystemName SourceSystemName { get; set; } 

    public MoveEntity() 
    { 
     PrimaryOriginTransferee = new TransfereeEntity(); 
     PrimaryDestinationTransferee = new TransfereeEntity(); 
     Customer = new CustomerEntity(); 
     OriginAddress = new AddressEntity(); 
     DestinationAddress = new AddressEntity(); 
     Order = new OrderEntity(); 
     Shipment = new ShipmentEntity(); 
    } 

    public bool HasShipment() 
    { 
     if (Shipment.ExternalShipmentId > 0) 
     { 
      return true; 
     } 
     return false; 
    } 
} 

這裏是業務對象(MoveEntity),我想從

地圖

每個類中的屬性幾乎完全按名稱匹配,但它們的類型不同。因此,我試圖使用「MapFrom」表達式執行自定義映射。但是,AutoMapper似乎無法讓我從一種對象類型指向另一種對象而沒有抱怨。

我也試過映射屬性到財產,沒有運氣。它看起來是這樣的:

.ForMember(dest => dest.PrimaryOriginTransferee.Email, opt => opt.MapFrom(src => src.PrimaryOriginTransferee.Email)) 

但是,試圖這樣的時候,我收到以下exeception:

必須解析到頂級成員。 參數名稱:lambdaExpression。

我一直在尋找可用於AutoMapper的文檔難以遵循。有人請指出我正確的方向,如何正確使用這個工具?

在此先感謝您的幫助!

亞當

+0

Wall O Text ....:〜( – 2012-01-12 12:27:51

+2

下一次我會確保信息不足,謝謝你的貢獻 – letsgetsilly 2012-01-13 16:11:31

+0

Lolz :) :) :) :) – 2012-01-14 02:54:45

回答

5

我終於結束了這個工作,我自己。我最終使用的代碼在下面發佈。以正確的順序創建對象圖是非常重要的。我通過這件事學到了很多東西。

我已將我的映射組織到一個配置文件中,我不會進入這裏,只要說如果您可以在繼承自AutoMapper配置文件類的類之外使用我的示例,則需要使用Mapper.CreateMap而不僅僅是創建地圖。

private void CreateMaps() 
    { 

     CreateMap<ContactEntity, TransfereeEntityDto>(); 

     //ContactEntity Mapping 
     CreateMap<ContactEntity, TransfereeEntityDto>(); 

     //CustomerEntity Mapping 
     CreateMap<CustomerEntity, CustomerEntityDto>(); 

     //AddressEntity Mapping 
     CreateMap<AddressEntity, AddressEntityDto>(); 

     //ServiceEntity Mapping 
     CreateMap<ServiceEntity, ServiceEntityDto>() 
      .ForMember(dto => dto.ServiceTypeCode, opt => opt.MapFrom(source => source.TypeCode)) 
      .ForMember(dto => dto.ServiceDescriptionCode, opt => opt.MapFrom(source => source.DescriptionCode)) 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 


     //VehicleEntity Mapping 
     CreateMap<VehicleEntity, VehicleEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)) 
      .ForMember(dto => dto.PortalId, option => option.Ignore()); //TODO: Should PortalID be mapped to anything? It is not in the entity. 

     //ContentEntity Mapping 
     CreateMap<ContentEntity, ContentEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 

     //OrderForwardingEntity Mapping 
     CreateMap<OrderForwardingEntity, OrderForwardingEntityDto>(); 

     //ContainerEntity Mapping 
     CreateMap<ContainerEntity, ContainerEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 

     //ShipmentForwardingEntity Mapping 
     CreateMap<ShipmentForwardingEntity, ShipmentForwardingEntityDto>(); 


     //ShipmentRouting Mapping 
     CreateMap<ShipmentRoutingEntity, ShipmentRoutingEntityDto>(); 

     //ShipmentEntity Mapping 
     CreateMap<ShipmentEntity, ShipmentEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)) 
      .ForMember(dto => dto.Services, option => option.MapFrom(source => source.ServiceEntities)); 

     //Forwarder mapping 
     CreateMap<ContactEntity, ForwarderEntityDto>(); 
     //TODO: This property doesn't have any properties in the data contract 

     //OrderEntity Mapping 
     CreateMap<OrderEntity, OrderEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, 
         opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 
      //.ForMember(dto => dto.Forwarder, option => option.MapFrom(entity=>entity.Forwarder) 

     //MoveEntityMapping 
     CreateMap<MoveEntity, MoveEntityDto>() 
      .ForMember(dto => dto.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 

    } 
1

您需要添加映射配置的屬性類型,其中目標屬性的類型是類型目標屬性的不同。

Mapper.CreateMap<ContactEntity, TransfereeEntity>(); 
4

我知道你已經得到了這個工作,但我會把它扔到那裏,以防其他人在這裏降落。

在AutoMapper中,如果有嵌套的對象需要映射,即使它們完全相同(即匹配的契約類和模型類),也必須爲子類定義映射,然後當定義父圖的地圖時,在'.ForMember'選項內,您可以使用這些子地圖來映射父圖。我知道這聽起來可能令人困惑,但一個例子會說清楚。

假設你有一個如下:

namespace Contracts.Entities 
{ 
    public class Person 
    { 
     public string FirstName {get; set;} 

     public string LastName {get; set;} 

     public Address Address {get; set;}   
    } 

    public class Address 
    { 
     public string Street {get; set;} 

     public string City {get; set;} 

     public string State {get; set;}   
    } 
} 

namespace Model.Entities 
{ 
    public class Person 
    { 
     public string FirstName {get; set;} 

     public string LastName {get; set;} 

     public Address Address {get; set;}   
    } 

    public class Address 
    { 
     public string Street {get; set;} 

     public string City {get; set;} 

     public string State {get; set;}   
    } 
} 

然後你去定義以下地圖:

Mapper.CreateMap<Contracts.Entities.Person, Model.Entities.Person>(); 
    Mapper.CreateMap<Contracts.Entities.Address, Model.Entities.Address>(); 

你可能會認爲AutoMapper會知道使用地址地圖繪製合同時人對一個模特人,但它沒有。取而代之的是,這裏是你必須做的:

 Mapper.CreateMap<Contracts.Entities.Person, Model.Entities.Person>() 
        .ForMember(dest => dest.Address, opt => opt.MapFrom(src => Mapper.Map<Contracts.Entities.Address, Model.Entities.Address>(src.Address))); 

Mapper.CreateMap<Contracts.Entities.Address, Model.Entities.Address>(); 

所以你的情況,你可以定義一個Mapper.CreateMap<ContactEntity,TransfereeEntity>()地圖然後調用以同樣的方式作爲地址映射定義地圖PrimaryOriginTransferee時上方。 I.E.

Mapper.CreateMap<MoveEntity, MoveEntityDto>() 
.ForMember(dest => dest.PrimaryOriginTransferee , opt => opt.MapFrom(src => Mapper.Map<ContactEntity,TransfereeEntity>(src.PrimaryOriginTransferee))); 

希望這可以幫助別人!