Отображение ICollection на объект с помощью Automapper - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь сопоставить ICollection of News с BreakingNewsDto:

    public class Division
    {
        public Division()
        {
            Newses = new HashSet<News>();
            Articles = new HashSet<Article>();
            Contacts = new HashSet<Contact>();
        }

        public string Name { get; set; }

        public virtual ICollection<News> Newses { get; }

        public virtual ICollection<Article> Articles { get; }

        public virtual ICollection<Contact> Contacts { get; }

        public Guid PhotoId { get; set; }

        public virtual Photo Image { get; set; }

        public bool IsActive { get; set; }
    }

    public class BreakingNewsDto
    {

        public BreakingNewsDto()
        {
            News = new List<NewsDto>();
        }
        public int TotalAmount { get; set; }

        public ICollection<NewsDto> News { get; set; }
    }    

public class NewsDto
    {
        public Guid Id { get; set; }

        public string HeadLine { get; set; }

        public string Slug { get; set; }

        public string Article { get; set; }

        public string Author { get; set; }
    }

В общем, все работало довольно хорошо, пока я не попытался добавить BreakingNewsDto для сопоставления Collection of News с Dto.Я использовал следующие сопоставления и преобразователи:

CreateMap<ICollection<News>, BreakingNewsDto>().ConvertUsing<NewsToBreakingNewsConverter>();

CreateMap<Division, FullDivisionDto>()
                .ForMember(dest => dest.News, a => a.MapFrom(src => src.Newses))
                .ForMember(dest => dest.UserId, a => a.Ignore());

public class NewsToBreakingNewsConverter : ITypeConverter<ICollection<News>, BreakingNewsDto>
{
    public BreakingNewsDto Convert(ICollection<News> source, BreakingNewsDto destination, ResolutionContext context)
    {
        destination.TotalAmount = source.Count;
        foreach (var news in source)
        {
           destination.News.Add(Mapper.Map<News, NewsDto>(news));
        }

        return destination;
    }
}

Когда я пытаюсь использовать это, я получаю следующее сообщение об ошибке:

> AutoMapper.AutoMapperMappingException: Error mapping types.
> 
> Mapping types: Division -> FullDivisionDto
> TsvMeine.Domain.Entities.Division ->
> TsvMeine.Application.Ressources.Division.FullDivisionDto
> 
> Type Map configuration: Division -> FullDivisionDto
> TsvMeine.Domain.Entities.Division ->
> TsvMeine.Application.Ressources.Division.FullDivisionDto
> 
> Destination Member: News  ---> System.NullReferenceException: Object
> reference not set to an instance of an object.    at
> TsvMeine.Application.MappingProfiles.Converters.NewsToBreakingNewsConverter.Convert(ICollection`1
> source, BreakingNewsDto destination, ResolutionContext context) in
> D:\Users\Jonas\VisualStudios\Enterprise\Website\Code\Core\Application\TsvMeine.Application\MappingProfiles\Converters\NewsToBreakingNewsConverter.cs:line
> 12    at lambda_method(Closure , Division , FullDivisionDto ,
> ResolutionContext )    --- End of inner exception stack trace ---   
> at lambda_method(Closure , Division , FullDivisionDto ,
> ResolutionContext )    at
> AutoMapper.Mapper.AutoMapper.IMapper.Map[TSource,TDestination](TSource
> source) in C:\projects\automapper\src\AutoMapper\Mapper.cs:line 233   
> at
> TsvMeine.Persistence.Services.DivisionService.GetDivisionAsync(Int32
> divisionId, Boolean overrideIsActive, CancellationToken token) in
> D:\Users\Jonas\VisualStudios\Enterprise\Website\Code\Infrastructure\Persistence\TsvMeine.Persistence\Services\DivisionService.cs:line
> 130

Из Stacktrace до сих пор я вижу этот пункт назначения в моемКонвертер является нулевым указателем.Поэтому я исправил это, добавив следующее:

public BreakingNewsDto Convert(ICollection<News> source, BreakingNewsDto destination, ResolutionContext context)
        {
            destination = new BreakingNewsDto();
            destination.TotalAmount = source.Count;
            foreach (var news in source)
            {
               destination.News.Add(Mapper.Map<News, NewsDto>(news));
            }

            return destination;
        }

Однако я все еще получаю сообщение об ошибке:

AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
Division -> FullDivisionDto
TsvMeine.Domain.Entities.Division -> TsvMeine.Application.Ressources.Division.FullDivisionDto

Type Map configuration:
Division -> FullDivisionDto
TsvMeine.Domain.Entities.Division -> TsvMeine.Application.Ressources.Division.FullDivisionDto

Элемент назначения: News ---> System.InvalidOperationException: Mapperне инициализирован.Вызовите Initialize с соответствующей конфигурацией.Если вы пытаетесь использовать экземпляры mapper через контейнер или иным образом, убедитесь, что у вас нет вызовов статических методов Mapper.Map, и если вы используете методы расширения ProjectTo или UseAsDataSource, убедитесь, что вы передаете соответствующий IConfigurationProvider.пример.в AutoMapper.Mapper.get_Instance () в C: \ projects \ automapper \ src \ AutoMapper \ Mapper.cs: строка 36 в AutoMapper.Mapper.Map [TSource, TDestination] (источник TSource) в C: \ projects \ automapper \ src\ AutoMapper \ Mapper.cs: строка 96 в TsvMeine.Application.MappingProfiles.Converters.NewsToBreakingNewsConverter.Convert (источник ICollection`1, назначение BreakingNewsDto, контекст ResolutionContext) в D: \ Users \ Jonas \ VisualStudios \ Core \ Website \ Code\ Application \ TsvMeine.Application \ MappingProfiles \ Converters \ NewsToBreakingNewsConverter.cs: строка 16 в lambda_method (закрытие, деление, FullDivisionDto, ResolutionContext) --- конец трассировки стека внутренних исключений --- в lambda_method (закрытие, деление, FullDivisionDto, ResolutionContete)) в AutoMapper.Mapper.AutoMapper.IMapper.Map [TSource, TDestination] (источник TSource) в C: \ projects \ automapper \ src \ AutoMapper \ Mapper.cs: строка 233 в TsvMeine.Persistence.Services.DivisionService.GetDivisionAsync (Int32)DivisionId, Boolean overrideIsActive, CancellationТокен) в D: \ Users \ Jonas \ VisualStudios \ Enterprise \ Website \ Code \ Infrastructure \ Persistence \ TsvMeine.Persistence \ Services \ DivisionService.cs: строка 130

Теперь у меня два вопроса:

  1. Что мне нужно сделать, чтобы получить инициализированный пункт назначения в моем конвертере вместо создания своего собственного?

  2. Как инициализировать мой картографправильно ли использовать его в Asp.Net Core Web API?

Edit

Извините Кажется, я забыл самую важную часть.Очевидно, что правильно использовать (и я уже использую) пакет Automapper DI, упомянутый в комментариях.Однако сейчас я пытаюсь выполнить модульное / интеграционное тестирование моих сервисов и тому подобного, и у меня нет моего DI-контейнера.Однако я все еще хочу использовать «настоящий» Automapper, а не поддельную реализацию, чтобы увидеть, правильны ли мои сопоставления.Поэтому я попытался настроить Automapper следующим образом:

    config = new MapperConfiguration(x =>
    {
        x.AddProfile<DomainToDtoMappingProfile>();
        x.AddProfile<DtoToDomainMappingProfile>();

    });
    _mapper = config.CreateMapper();

Однако этого недостаточно для того, чтобы конверсия работала.Так что мои два вопроса все еще остаются.

...