Проблема
У меня есть модель предметной области, в которую встроена система проверки. Концептуально это выглядит так:
Model -> ModelDetails
Модель поддерживает все отношения с другими объектами и имеет ICollection
из ModelDetails
. Он также имеет свойство details
, которое показывает последнюю версию. До сих пор я сопоставлял все с помощью ручного кодирования для моделей представления. По сути, это комбинация объектов Model
и ModelDetails
(свойство деталей). Проблема заключается в том, чтобы определить, что отображение модели представления происходит как из свойства Model
, так и из свойства Details
(модель ModelDetails
).
В приведенном ниже примере я могу сделать это, используя дополнительный вызов, но тогда мне нужно будет поместить этот вызов в каждое место преобразования, а не только один вызов сопоставления. Еще одна сложность заключается в том, что, поскольку отношения отображаются, я не могу справиться с пересмотром отношений atm.
Модели предметной области
public class Model : RevisionBasedModel<Revisions.ModelDetails>
{
public int Id { get; set; }
public virtual ICollection<ModelTwo> RelationExample { get; set; }
= new HashSet<ModelTwo>();
}
public abstract class RevisionBasedModel<TRevision> : IRevisionBasedModel<TRevision>
{
public TRevision Details
{
get { return Revisions.OrderByDescending(x => x.TimeStamp).First();
}
public virtual ICollection<TRevision> Revisions { get; set; }
= new HashSet<TRevision>();
}
public class ModelDetails {
public int Id { get; set; }
public string PropertyOne { get; set; }
public string PropertyTwo { get; set; }
}
Модель представления
public class ModelVM {
public int Id { get; set; }
public int RevisionId { get; set; }
public string PropertyOne { get; set; }
public string PropertyTwo { get; set; }
public ICollection<ModelTwoVM> RelationExample { get; set; }
= new HashSet<ModelTwoVM>
}
Текущая конфигурация сопоставления
CreateMap<Model, ModelVM>()
.ForMember(x => x.RelationExample, opt => opt.MapFrom(y => y.RelationExample));
CreateMap<ModelDetails, ModelVM>()
.ForMember(x => x.RevisionId, opt => opt.MapFrom(y => y.Id));
CreateMap<ModelTwo, ModelTwoVM>();
CreateMap<ModelTwoDetails, ModelTwoVM>()
.ForMember(x => x.RevisionId, opt => opt.MapFrom(y => y.Id));
Текущая конверсия
var viewModel = this._mapper.Map<Model, ModelVM>(model);
viewModel = this._mapper.Map<ModelDetails, ModelVM>(model.Details, viewModel);
ОБНОВЛЕНИЕ 24 января 2017 г., 19:26
В комментариях было предложено возможный «грубый» способ с использованием преобразователя пользовательского типа. Мне удалось заставить часть ревизии работать, но из-за того, что сопоставление по умолчанию было перезаписано, я потерял сопоставление отношений.
public class RevisionConverter<TModel, TRevision, TViewModel> : ITypeConverter<TModel, TViewModel>
where TModel : IRevisionBasedModel<int, TRevision>
{
public TViewModel Convert(TModel source, TViewModel destination, ResolutionContext context)
{
return context.Mapper.Map<TRevision, TViewModel>(source.Details, destination);
}
}