2015-09-28 2 views
0

В моих данных у меня есть два объекта, которые могут иметь адрес. В базе данных эти столбцы дублируются в каждой таблице. Я мог бы нормализовать их в будущем, но не хочу заниматься этим в данный момент. Однако, на мой взгляд, у меня есть контактная информация, которая разворачивается в отдельный класс, который используется повторно.AutoMapper отображает наследуемые свойства из подкласса

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

Вот классы сущностей данных (упрощенный немного):

public abstract class EntityWithContactInfo 
{ 
    [MaxLength(50)] 
    public string Street1 { get; set; } 

    [MaxLength(50)] 
    public string Street2 { get; set; } 

    [MaxLength(30)] 
    public string City { get; set; } 

    [MaxLength(30)] 
    public string State { get; set; } 

    [MaxLength(10)] 
    public string Zip { get; set; } 

    [MaxLength(10)] 
    public string Phone { get; set; } 

    [MaxLength(100)] 
    public string Email { get; set; } 
} 

public class Organization : EntityWithContactInfo 
{ 
    public int OrganizationId { get; set; } 

    [MaxLength(100), Required] 
    public string FullName { get; set; } 

    [MaxLength(100), Required] 
    public string DisplayName { get; set; } 

    public string Website { get; set; } 

    public string Information { get; set; } 
} 

public class Agent : EntityWithContactInfo 
{ 
    public int AgentId { get; set; } 

    [MaxLength(30), Required] 
    public string LastName { get; set; } 

    [MaxLength(20), Required] 
    public string FirstName { get; set; } 

    public string Comments { get; set; } 
} 

А вот мой вид модели (я не один для агента еще - работа по организации первого):

public class ContactInfoEditModel 
{ 
    [StringLength(50)] 
    [Display(Name = "Street Address 1")] 
    public string Street1 { get; set; } 

    [StringLength(50)] 
    [Display(Name = "Street Address 2")] 
    public string Street2 { get; set; } 

    [StringLength(30)] 
    public string City { get; set; } 

    [StringLength(30)] 
    public string State { get; set; } 

    [StringLength(10)] 
    public string Zip { get; set; } 

    [Display(Name = "Pimary Phone")] 
    public string Phone { get; set; } 

    [StringLength(100)] 
    [Display(Name = "Email Address")] 
    public string Email { get; set; } 
} 

public abstract class EditModelBaseWithContactInfo 
{ 
    [Display(Name = "Contact Information")] 
    public ContactInfoEditModel ContactInfo { get; set; } 
} 

public class OrganizationEditModel : EditModelBaseWithContactInfo 
{ 
    [Display(Name = "Id")] 
    public int OrganizationId { get; set; } 

    [Required, StringLength(100)] 
    [Display(Name = "Full Name")] 
    public string FullName { get; set; } 

    [Required, StringLength(100)] 
    [Display(Name = "Display Name")] 
    public string DisplayName { get; set; } 

    [Url(ErrorMessage = "Please enter a valid URL (including the protocol: http:// or https://).")] 
    public string Website { get; set; } 

    [UIHint("HtmlEditor")] 
    [AllowHtml] 
    public string Information { get; set; } 
} 

Что я для отображения прямо сейчас выглядит следующим образом:

Mapper.CreateMap<EntityWithContactInfo, ContactInfoEditModel>(); 

Mapper.CreateMap<Organization, OrganizationEditModel>() 
     .MapEditModelBaseWithContactInfo(); 

Mapper.CreateMap<OrganizationEditModel, Organization>() 
     .MapEntityWithContactInfo(); 


private static IMappingExpression<TEntity, TModel> MapEditModelBaseWithContactInfo<TEntity, TModel>(this IMappingExpression<TEntity, TModel> mapping) 
    where TEntity : EntityWithContactInfo 
    where TModel : EditModelBaseWithContactInfo 
{ 
    return mapping.ForMember(m => m.ContactInfo, exp => exp.MapFrom(e => Mapper.Map<ContactInfoEditModel>(e))); 
} 

private static IMappingExpression<TModel, TEntity> MapEntityWithContactInfo<TModel, TEntity>(this IMappingExpression<TModel, TEntity> mapping) 
    where TModel : EditModelBaseWithContactInfo 
    where TEntity : EntityWithContactInfo 
{ 
    return mapping.MapEntityModifiable() 
        .ForMember(e => e.Street1, exp => exp.MapFrom(m => m.ContactInfo.Street1)) 
        .ForMember(e => e.Street2, exp => exp.MapFrom(m => m.ContactInfo.Street2)) 
        .ForMember(e => e.City, exp => exp.MapFrom(m => m.ContactInfo.City)) 
        .ForMember(e => e.State, exp => exp.MapFrom(m => m.ContactInfo.State)) 
        .ForMember(e => e.Zip, exp => exp.MapFrom(m => m.ContactInfo.Zip)) 
        .ForMember(e => e.Email, exp => exp.MapFrom(m => m.ContactInfo.Email)) 
        .ForMember(e => e.State, exp => exp.MapFrom(m => m.ContactInfo.State)) 
        .ForMember(e => e.Phone, exp => exp.MapFrom(m => m.ContactInfo.Phone)); 
} 

Я сделал два последних расширения встретились hods в моем статическом классе сопоставления, так что, когда я добавляю сопоставления Агента, мне не нужно дублировать вызовы .ForMember. Как вы можете видеть, сопоставление модели данных для просмотра модели выглядит неплохо. Второй метод расширения - это то, где я боюсь. Он работает просто отлично, но это не похоже на . Правило способ сделать это. Как вы можете видеть, у меня есть все свойства в Organization/ContactInfo, указанные в явном виде, хотя все они имеют одинаковые имена (которые AutoMapper обычно обрабатывает самостоятельно)

Кажется, должен быть способ сообщить AutoMapper сопоставьте все свойства свойства ContactInfo источника непосредственно с Destination. Кто-нибудь знает, как вы это сделаете? Я играл с Include <> и IncludeBase <>.

Я также рассмотрели имеющим OrganizationEditModel наследовать от ContactInfoEditModel непосредственно, но я не был уверен в том, что мощи испортить мои EditorTemplates (и что все еще чувствует, как обходной путь, а не решение права).

ответ

0

Посмотрите на ConvertUsing. Второй метод расширения может выглядеть следующим образом:

private static IMappingExpression<TModel, TEntity> MapEntityWithContactInfo<TModel, TEntity>(this IMappingExpression<TModel, TEntity> mapping) 
    where TModel : EditModelBaseWithContactInfo 
    where TEntity : EntityWithContactInfo 
{ 
    return mapping.MapEntityModifiable() 
     .ConvertUsing(x => Mapper.Map<TEntity>(x.ContactInfo)); 
} 
+0

Я попробовал, и это потребовало отображение ContactInfoEditModel к Организации (с Ignore() положений для всех Организации конкретных областей), но теперь отображение не копирование ** любых ** данных из модели представления в модель данных. – jfren484

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