2010-01-12 3 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 впервые для того, чтобы отобразить от Bussiness объекта к 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), что я пытаюсь карту от

public class MoveEntity 
{ 
    public int SourceId { get; set; } 
    public int MoveId { get; set; } 
    public bool IsOrderDetailPageModified { get; set; } // TODO: Internal - Remove from data contract 
    public bool IsRoutingPageModified { get; set; } // TODO: Internal - Remove from data contract 
    public bool IsServicePageModified { get; set; } // TODO: Internal - Remove from data contract 
    public bool IsContentAndContainerPageModified { get; set; } // Rmove from data contract 
    public string FamilyRange { get; set; } // TODO: Is this being used? 
    public string Office { get; set; } 
    public string ActivityType { get; set; } 
    public string ActivitySubject { get; set; } 
    public string ActivityNote { get; set; } 
    public ContactEntity PrimaryOriginTransferee { get; set; } 
    public ContactEntity 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 CreatedBy { get; set; } 
    public DateTime CreatedDate { get; set; } 
    public string ModifiedBy { get; set; } 
    public DateTime ModifiedDate { get; set; } 
    public string SourceSystemId { get; set; } 
    public string SourceSystemName { get; set; } 
    public string Version { get; set; } 
    public string PortalId { get; set; } 

    public MoveEntity() 
    { 
     PrimaryOriginTransferee = new ContactEntity 
     { 
      ContactTypeId = ContactEntity.ContactType.PrimaryOriginationTransferee 
     }; 

     PrimaryDestinationTransferee = new ContactEntity 
     { 
      ContactTypeId = ContactEntity.ContactType.PrimaryDestinationTransferee 
     }; 

     OriginAddress = new AddressEntity 
     { 
      AddressTypeId = AddressEntity.AddressType.Origination 
     }; 

     DestinationAddress = new AddressEntity 
     { 
      AddressTypeId = AddressEntity.AddressType.Destination 
     }; 

     Order = new OrderEntity(); 
     Customer = new CustomerEntity(); 
     Shipment = new ShipmentEntity(); 
    } 

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

Свойства в каждом классе почти полностью совпадают по названию, но их типы разные. Поэтому я попытался выполнить пользовательское сопоставление, используя выражение «MapFrom». Тем не менее, AutoMapper, похоже, не позволяет мне указывать один тип объекта другому без жалобы.

Я также пробовал сопоставлять свойство собственности, без везения. Это выглядело примерно так:

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

Однако при попытке это, я получаю следующее exeception:

должен разрешить члену верхнего уровня. Имя параметра: lambdaExpression.

Я нашел документацию, доступную для AutoMapper, которой сложно следовать. Может ли кто-нибудь указать мне в правильном направлении, как правильно использовать эту утилиту?

Заранее благодарим за любую помощь!

Адам

+0

Wall O Text ....: ~ ( –

+2

В следующий раз я буду уверен, что информации недостаточно. Спасибо за ваш вклад. – letsgetsilly

+0

Lolz :) :) :) :) –

ответ

5

Я, наконец, закончил работу над этим самостоятельно. Код, который я использовал, опубликован ниже. Создание карты объектов в правильном порядке оказалось важным. Я многому научился этому.

Я организовал мои сопоставления в профиль, который я не получу здесь, достаточно сказать, что если вы можете использовать мой пример вне класса, наследующего класс AutoMapper Profile, вы захотите использовать 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. И.Е.

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

Надеюсь, это поможет кому-то!

Смежные вопросы