使用Automapper将ICollection映射到对象

时间:2018-11-27 00:30:11

标签: c# unit-testing automapper asp.net-core-webapi nunit-3.0

我正在尝试将新闻的ICollection映射到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以便将新闻集映射到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中,我可以看到Converter中的目标是一个Nullpointer。所以我通过添加以下内容解决了该问题:

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
     

目的地会员:       新闻        ---> System.InvalidOperationException:映射器未初始化。用适当的配置调用初始化。如果您尝试通过容器或其他方式使用mapper实例,请确保没有对静态Mapper.Map方法的任何调用,并且如果您使用的是ProjectTo或UseAsDataSource扩展方法,请确保传递适当的IConfigurationProvider实例。          在C:\ projects \ automapper \ src \ AutoMapper \ Mapper.cs:第36行中的AutoMapper.Mapper.get_Instance()中          在C:\ projects \ automapper \ src \ AutoMapper \ Mapper.cs:line 96中的AutoMapper.Mapper.Map [TSource,TDestination](TSource源)          在TsvMeine.Application.MappingProfiles.Converters.NewsToBreakingNewsConverter.Convert(ICollection`1源,BreakingNewsDto目标,ResolutionContext上下文)中的D:\ Users \ Jonas \ VisualStudios \ Enterprise \ Website \ Code \ Core \ Application \ TsvMeine.Application \ MappingProfiles \ Converters \ NewsToBreakingNewsConverter.cs:第16行          at lambda_method(Closure,Division,FullDivisionDto,ResolutionContext)          ---内部异常堆栈跟踪的结尾---          at lambda_method(Closure,Division,FullDivisionDto,ResolutionContext)          在C:\ projects \ automapper \ src \ AutoMapper \ Mapper.cs:line 233中的AutoMapper.Mapper.AutoMapper.IMapper.Map [TSource,TDestination](TSource源)处          在Ds:\ Users \ Jonas \ VisualStudios \ Enterprise \ Website \ Code \ Infrastructure \ Persistence \ TsvMeine.Persistence \ Services \ DivisionService.cs中的Ds:第130

现在我有两个问题:

  1. 我该怎么办才能在Converter中获取初始化的目的地,而不是创建自己的目的地?

  2. 如何正确初始化Mapper以便在Asp.Net Core Web API中使用它?

编辑

抱歉,我似乎忘记了最相关的部分。显然,使用(并且我已经在使用)注释中提到的Automapper DI软件包是正确的。但是,现在我正在尝试对服务以及类似的东西进行单元/集成测试,并且那里没有DI​​容器。但是,我仍然想使用“真实的”自动映射器而不是伪造的实现来查看我的映射是否正确。因此,我试图像这样设置Automapper:

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

    });
    _mapper = config.CreateMapper();

但是,这似乎不足以使转换正常工作。 所以我的两个问题仍然存在。

0 个答案:

没有答案