Подтвердить что ты не робот

Наследование AutoMapper и Linq

Я искал, как использовать Inheritance в AutoMapper, но я изо всех сил стараюсь полностью работать с Linq. Вот мой код:

Я определил свои отображения здесь:

CreateMap<Article, ArticleDetailsViewModel>()
    .Include<Article, ArticleNewsItemDetailsViewModel();

CreateMap<Article, ArticleNewsItemDetailsViewModel>();

ArticleDetailsViewModel является базовым классом ArticleNewsItemDetailsViewModel.

Теперь вот проблема, если бы у меня было:

CreateMap<ArticleNewsItem, ArticleNewsItemDetailsViewModel>();

Все свойства в модели представления будут автоматически отображаться, потому что они имеют то же имя, что и их эквивалент объекта Linq. Однако, потому что я использую сопоставление Article => ArticleNewsItemDetailsViewModel, это невозможно, вместо этого я должен был бы определить каждый из них как:

.ForMember(x => x.Property1, opt => opt.MapFrom(src => src.ArticleNewsItem.Property1)

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

Есть ли способ избежать этого?

4b9b3361

Ответ 1

Предположим, что у вас есть следующие классы:

    public class Article
    {
        public string Prop1 { get; set; }
        public string Prop2 { get; set; }
        public ArticleNewsItem ArticleNewsItem { get; set; }
    }

    public class ArticleDetailsViewModel
    {
        public string Prop1 { get; set; }
    }

    public class ArticleNewsItemDetailsViewModel : ArticleDetailsViewModel
    {
        public string Prop2 { get; set; }
        public string Prop3 { get; set; }
    }

    public class ArticleNewsItem
    {
        public string Prop3 { get; set; }
    }

Отображение должно выглядеть следующим образом:

var res = Mapper.Map<Article, ArticleNewsItemDetailsViewModel>(_article);
Mapper.Map(_article.ArticleNewsItem, res);

Кроме того, вы можете создать преобразователь пользовательского типа, чтобы избежать записи этих двух строк каждый раз, когда вам нужно сопоставить Article с ArticleNewsItemDetailsViewModel.

Ответ 2

Извиняюсь, если я больше упрощаю это в своей голове, но вы не можете просто добавить указанное прямое сопоставление:

CreateMap<ArticleNewsItem, ArticleNewsItemDetailsViewModel>();

Для меня это самое простое и чистое решение...

ИЗМЕНИТЬ Извините, я неправильно понял. Вы не можете сопоставить объект с вложенным свойством, не создавая настраиваемую карту через методы .ConstructUsing() или .ConvertUsing() (или делать это неопрятный путь)...

Mapper.CreateMap<Article, ArticleNewsItemDetailsViewModel>().ConstructUsing(ConstructItem)

.. Затем создайте свой метод для создания объекта ArticleNewsItemDetailsViewModel...

private static ArticleNewsItemDetailsViewModel ConstructItem(Article source)
    {
        var newsItem = new ArticleNewsItem
                           {
                               Prop1 = source.Prop1,
                               Prop2 = source.Prop2
                           };

        var result = new ArticleNewsItemDetailsViewModel()
                         {
                             ArticleNewsItem = newsItem
                         };

        return result;
    }

Однако я бы порекомендовал повторно реализовать ваше решение, чтобы вы отображали "как будто". Вот хороший пример: http://automapper.codeplex.com/wikipage?title=Nested%20Mappings

Ответ 3

Предполагая, что все необходимые свойства находятся в статье, вы можете создать Custom Value Resolver, чтобы сделать это, например.

public class ArticleNewsItemResolver : ValueResolver<Article, ArticleNewsItem>
{
    protected override ArticleNewsItem ResolveCore(Article source)
    {
        return Mapper.DynamicMap<Article, ArticleNewsItem>(source);
    }
}
...

CreateMap<Article, ArticleNewsItemDetailsViewModel>()
    .ForMember(src => src.NewsItem, opt => opt.ResolveUsing<ArticleNewsItemResolver>());