В моих данных у меня есть два объекта, которые могут иметь адрес. В базе данных эти столбцы дублируются в каждой таблице. Я мог бы нормализовать их в будущем, но не хочу заниматься этим в данный момент. Однако, на мой взгляд, у меня есть контактная информация, которая разворачивается в отдельный класс, который используется повторно.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 (и что все еще чувствует, как обходной путь, а не решение права).
Я попробовал, и это потребовало отображение ContactInfoEditModel к Организации (с Ignore() положений для всех Организации конкретных областей), но теперь отображение не копирование ** любых ** данных из модели представления в модель данных. – jfren484