Using string.Split() in AutoMapper issue

一曲冷凌霜 提交于 2021-02-20 19:12:51

问题


I have an ASP .Net core application. I am simply trying to have my AutoMapper configure to convert a string comma delimited into a list of strings as per this configuration:

configuration.CreateMap<Job, JobDto>()
             .ForMember(dto => dto.Keywords, options => options.MapFrom(entity => entity.Keywords.Split(',').ToList()))

For some reason it does not get compiled and give me the following error:

An expression tree may not contain a call or invocation that uses optional argument

I can't see why I am getting this error. I am pretty sure that I have done that in my other projects before without any such error.


回答1:


This is completely true.

Error is raised because expression tree being created is about to contain some more complex logic, like .Split(',').ToList(), which is not an accessible property or method, only top-level reflected object properties and methods are supported (like in class MemberInfo).

Property chaining, deep-calls (.obj1property.obj2property), extension methods are not supported by the expression trees, like in this .ToList() call.

My solution was like this:

// Execute a custom function to the source and/or destination types after member mapping
configuration.CreateMap<Job, JobDto>()
  .AfterMap((dto,jobDto)=>jobDto.Keywords = dto.Keywords.Split(',').ToList());



回答2:


As error says, Split function has an optional parameter. The full signature of it is as this (options is optional)

public string[] Split(string separator, StringSplitOptions options = StringSplitOptions.None)

As you are trying to use a function with default value inside an expression tree, it gives you the error. To Fix it, easy, just pass on optional parameters by yourself. ( StringSplitOptions.None ) So, simply change it to this:

entity.Keywords.Split(',' , StringSplitOptions.None).ToList()



回答3:


I had the same problem. I do not know if it is an issue or not. Anyway, I found a workaround.

 CreateMap<Category, GetCategoryRest>()
                .ForMember(dest => dest.Words, 
                    opt => opt.MapFrom(src => ToWordsList(src.Words)));

 private static List<string> ToWordsList(string words)
 {
   return string.IsNullOrWhiteSpace(words) ? new List<string>() : words.Split(",").ToList();
 }

It is guaranteed that AutoMapper has always a List. Still, I'm confused. In my Startup.cs I define that AutoMapper allows null values for list.

Mapper.Initialize(cfg => {
 cfg.AllowNullCollections = true;
}

Category.Words is a string. GetCategoryRest.Words is a List<string>

AutoMapper Version: 8.1.1, AutoMapper.Microsoft.DependencyInjection: 6.1.1




回答4:


Use .AfterMap

 CreateMap<src, dto>()
                .ForMember(src =>src.Categories,options=> options.Ignore())
                .AfterMap((src, dto) => { dto.Categories.AddRange(src.Categories.Split(",").ToList()); })
                .ReverseMap()
                .ForMember(src => src.Categories, option => option.MapFrom(dto => string.Join(",", dto.Categories)));


来源:https://stackoverflow.com/questions/54858116/using-string-split-in-automapper-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!